Skocz do zawartości

Witamy w Nieoficjalnym polskim support'cie AMX Mod X

Witamy w Nieoficjalnym polskim support'cie AMX Mod X, jak w większości społeczności internetowych musisz się zarejestrować aby móc odpowiadać lub zakładać nowe tematy, ale nie bój się to jest prosty proces w którym wymagamy minimalnych informacji.
  • Rozpoczynaj nowe tematy i odpowiedaj na inne
  • Zapisz się do tematów i for, aby otrzymywać automatyczne uaktualnienia
  • Dodawaj wydarzenia do kalendarza społecznościowego
  • Stwórz swój własny profil i zdobywaj nowych znajomych
  • Zdobywaj nowe doświadczenia

Dołączona grafika Dołączona grafika

Guest Message by DevFuse
 

grankee - zdjęcie

grankee

Rejestracja: 06.06.2008
Aktualnie: Nieaktywny
Poza forum Ostatnio: 22.06.2017 21:14
****-

#455557 Bonusy wypadające z graczy.

Napisane przez ric0 w 04.09.2012 17:01

Witam. Plugin napisany według tego tematu : http://amxx.pl/topic...-pluginu-bonus/
Funkcję tworzenia paczki po zginięciu zapożyczyłem z tego tematu : http://amxx.pl/topic...turki-leczenia/ .
Mam na dzieję że radim się nie obrazi .(próbowałem się z nim skontaktować ale mi to nie wyszło :P

Dołączona grafika

Po zabiciu wroga wypada z niego paczka . Po zebraniu paczki losuję się bonus.
Bonusy do wylosowania:
Trucizna od -5 do -20 HP
Apteczka od 5 do 40 HP
Sakiewki ze złotem od 20 do 5000$
Losowy exp od 30 do 250
Losowy perk.

Dołączona grafika
Standardowa : http://amxx.pl/topic...-pluginow-amxx/
model z załącznika dodajemy bezpośrednio do folderu models.


----------------------Wersja dla Coda Starego----------------------
http://amxx.pl/topic..._20#entry456219

Dołączona grafika

Załączone pliki


  • +
  • -
  • 44


#283574 Przygotowanie stanowiska pracy - Notepad++

Napisane przez DarkGL w 16.08.2011 11:03

Notepad++ Przygotowanie stanowiska pracy

Dlaczego notepad++ ?
Jest kilka powodów :
  • Nie muli przy 8k linijek (tak jak np. amxx-studio)
  • Pozwala używać polskich znaków bez żadnego include
  • Wygodny
  • Posiada wiele przydatnych funkcji


Instalacja programu:
  • Na początek musimy oczywiście ściągnąć notepad++

    Oficjalna strona programu
    obecnie najnowsza wersja to v5.9.3
    proponuje ściągnąć
    Notepad++ v5.9.3 Installer
  • Instalacja jest bardzo prosta jedynie należy uważać aby

    podczas instalacji ta opcja była odznaczona
    opcja.JPG


Styl:

Standardowy styl notepad++ dla mnie średnio nadaje się do programowania pokaże jak go zmienić Dołączona grafika
  • W górnym menu programu wybieramy ustawienia a potem konfigurator stylów
  • W nowym oknie możemy wybrać jeden z dostępnych styli

    opcja6.JPG


Kolory składni na standardowym stylu:

Jeśli chcemy pisać na standardowym stylu notepad++ możemy wgrać 1 plik dzięki któremu składnia będzie kolorowana wygląda to tak
skladnia.JPG
  • Ściągamy ten plik
    Załączony plik  userDefineLang.rar   5,94 KB  2654 Ilość pobrań

  • W eksploratorze windows wpisujemy

    %appdata%\Notepad++

    opcja2.JPG
  • Kopiujemy 1 plik (userDefineLang.xml) z rozpakowanego archiwum które ściągnęliśmy przed chwilą do folderu który się nam otworzył

Styl do programowania:
  • Ściągamy ten plik
    Załączony plik  pawnIntegrated.rar   20,71 KB  3666 Ilość pobrań

  • W eksploratorze windows wpisujemy

    %appdata%\Notepad++

    opcja2.JPG
  • Kopiujemy 2 pliki z rozpakowanego archiwum które ściągnęliśmy przed chwilą do folderu który się nam otworzył ma to wyglądać tak

    opcja3.JPG
  • Tak wygląda plik sma po otwarciu
    wygladstyl.JPG
    według mnie dużo czytelniej :)


Styl jak AMXX Studio / Pawn Studio:
Dla osób które przyzwyczaiły się do AMXX Studio / Pawn Studio polecam ten styl kolory są te same jak w tych programach ;]
  • Ściągamy ten plik
    Załączony plik  userDefineLang.zip   15,53 KB  1225 Ilość pobrań

  • W eksploratorze windows wpisujemy

    %appdata%\Notepad++

    opcja2.JPG
  • Kopiujemy 1 plik (userDefineLang.xml) z rozpakowanego archiwum które ściągnęliśmy przed chwilą do folderu który się nam otworzył
    Wygląda to tak
    amxxstyl.JPG


Powiązanie plików:
  • Włączamy teraz notepad++ z górnego menu wybieramy Ustawienia->Preferencje potem wybieramy zakładkę Powiązanie plików wybieramy customize następnie dodajemy pliki sma i inc o tak

    opcja4.JPG
    opcja5.JPG
  • Punkt dla osób które podczas robienia rzeczy w podpunkcie wyżej miały zainstalowane na komputerze AMXX Studio lub PAWN Studio
  • Wchodzimy w panel sterowania

    opcja7.JPG
  • Przełączamy do widoku klasycznego



    opcja8.JPG
  • Klikamy dwa razy na "opcje folderów"
  • W nowym oknie wybieramy zakładkę "Typy plików"
  • Znajdujemy rozszerzenie .sma i klikamy zamień (jeśli nie znajdziemy to po prostu klikamy nowy i dodajemy ;) )



    opcja9.JPG
  • Znajdujemy na liście notepad++ i klikamy ok



    opcja10.JPG
  • Powtarzamy dwa punkty powyżej dla rozszerzenia .inc (zamiast sma szukamy inc Dołączona grafika )


TextFX Auto poprawianie tabulacji:

W AMXX Studio i Pawn Studio mieliśmy bardzo przydatną funkcje poprawiania tabulacji kodu (tools->indenter) w notepad++ też możemy ją mieć i to nawet lepiej działającą.
  • Wchodzimy tutaj
    manager.JPG
  • W zakładce "Available" znajdujemy "TextFX Characters" i instalujemy
    textfx.JPG
    będzie potrzebny restart notepad++
  • Po restarcie w górnym menu widzimy nową zakładkę "TextFX" ma ona bardzo wiele opcji (polecam się pobawić ;) ) ale interesuje nas tylko jedna "Reindent C++ code" która jest w "TextFX Edit" jej użycie mając otwarty plik sma powoduje uporządkowanie kodu.
    reindent.JPG
    Przed:
    przed.JPG
    Po:
    po.JPG


Kompilacja pluginów:

Notepad++ pozwala też na ustawienie sobie kompilacji pluginu pod klawisz :)
  • Wchodzimy tutaj
    manager.JPG
  • W zakładce "Available" znajdujemy "NppExec" i instalujemy
    nppexec.JPG
    będzie potrzebny restart notepad++
  • Po restarcie wchodzimy w opcje Pluginy -> NppExec -> Execute
    execute.JPG
  • W oknie które nam się pojawi wklejamy taki kod
    cd $(CURRENT_DIRECTORY)
    			"E:\Documents and Settings\DarkaGL\Pulpit\compiler\amxxpc.exe" "$(FILE_NAME)"
    oczywiście zamiast "E:\Documents and Settings\DarkaGL\Pulpit\compiler\amxxpc.exe" podajemy własną ścieżkę do pliku amxxpc.exe
    radzę poczytać o kompilacji lokalnej http://amxx.pl/topic...ilowac-pluginy/
    Klikamy save i nadajemy nazwę "AMXX Compiler"
  • Wchodzimy teraz w Pluginy -> NppExec -> Advanced Options
  • Pokaże się nam nowe okno w Item Name wpisujemy "AMXX Compiler"
    a w Associated Scripts wybieramy AMXX Compiler (chyba że ustawiliśmy inna nazwę w punkcie wyżej ;) )
  • Klikamy Add/Modify i OK
  • Restartujemy Notepad++
  • Po restarcie wchodzimy w Ustawienia -> Skróty Klawiszowe
  • W zakładce Plugin commands znajdujemy AMXX Compiler i klikamy na niego 2 razy
    commands.JPG
  • Otworzy się nam nowe okno w którym ustawiamy pod jakim klawiszem mamy kompilacje ja wybrałem F9
    commands2.JPG
    możemy oczywiście jaki chcemy ;)
  • Klikamy OK a potem Close i to wszystko kompilacja jest już pod wybranym klawiszem



Auto podpowiadanie składni:
  • Ściągamy ten plik
    Załączony plik  autocomplete.rar   36,76 KB  1687 Ilość pobrań

  • Wchodzimy do
    Program Files\Notepad++\plugins\APIs
    i kopiujemy do tego folderu rozpakowane pliki ze ściągniętego archiwum
  • Otwieramy Notepad++. Ustawienia -> Preferencje -> Zakładka Kopia/Auto-uzupełnianie
  • Zaznaczamy "Włącz auto-uzupełnianie" możemy też zaznaczyć podpowiadanie parametrów funkcji , w prawym górnym rogu widzimy od ... znaków podajemy tutaj liczbę znaków od kiedy notepad++ ma podpowiadać nazwę
    U mnie wygląda to tak
    autouzu.JPG
  • Po ustawieniu wszystkiego klikamy Zamknij gotowe :) !
    A tak wygląda podpowiadanie nazwy funkcji
    autouzupel.JPG


Używane polskich znaków:
Aby używać polskich znaków w pluginie należy
  • Otworzyć plik sma
  • W górnym menu wybrać zakładkę Format
  • Wybrać "Koduj w UTF-8 (bez BOM)" lub "Konwertuj na format UTF-8 bez BOM"
  • Zapisać plik i to tyle kompilujemy normalnie.

  • +
  • -
  • 70


#723478 [KOSZ] set_user_flags?

Napisane przez vanillah w 26.03.2016 16:50

potrzebne bedzie mysql


  • +
  • -
  • 0


#722243 Problem Paintball

Napisane przez marhalec w 04.03.2016 07:03

NIe zgubiłem dwóch zer jak napisałeś, ale temat można już zamknąć już dawno sobie poradziłem :)


  • +
  • -
  • -1


#718541 Urywanie 0.1 z float.

Napisane przez Oddaj Wiertarke w 19.01.2016 10:26

Pomnóż przez 10, zapisz jako zwyklego inta a przy odczytywaniu podziel przez 10 i powinien ci wyjsc float


  • +
  • -
  • 2


#718406 Jak pozbyc sie dzwieku topienia.

Napisane przez RaS_ w 17.01.2016 18:43

W folderze cstrike/sound/player tam go znajdziesz
  • +
  • -
  • 0


#697992 Możliwość blokowania wyświetlania informacji z consoli gracza ?

Napisane przez Amaroq w 19.04.2015 12:39

Moim zdaniem ten warunek

if(!containi(authid,"STEAM_ID") && !containi(authid,"VALVE"))
        return PLUGIN_CONTINUE

powinien wyglądać tak

if(containi(authid,"STEAM_ID") == -1 && containi(authid,"VALVE") == -1)
        return PLUGIN_CONTINUE

  • +
  • -
  • 3


#695344 [ROZWIĄZANE] Przerobienie pluginu

Napisane przez ferN94 w 02.04.2015 19:21

Już sobie dałem sam radę.Ale dzięki wszystkim za chęci pomocy.


  • +
  • -
  • -1


#688067 Problem z wygenerowaniem vipa w generator vipa

Napisane przez MordeKPrinc w 13.02.2015 15:45

A kombinowałeś ze znakami specjalnymi w Prefixie? Też tak miałem
  • +
  • -
  • -1


#682389 [ROZWIĄZANE] Czy żywy gracz może być nie połączony? (is_user_alive)

Napisane przez Ossal w 11.01.2015 15:13

Jak widać tylko Wielkie Jol potrafił wyjaśnić co i dlaczego, łap plusa, odpowiedź udzielona :)


  • +
  • -
  • -2


#681608 Roundsoundy słyszy tylko administracja

Napisane przez CoJestXdd w 07.01.2015 20:55

A dobrze dodałeś muzykę na FastDL/FTP serwera?


  • +
  • -
  • 0


#679311 Problem z find_ent_in_sphere.

Napisane przez NoLiFeR w 31.12.2014 12:52

Chcesz usuwać po classname ?

 

public find_ents_around(id){
	new Float:fOrigin[3]; // tworzymy tablicę na współrzędne bytu
	entity_get_vector(id, EV_VEC_origin, origin); // pobieramy współrzędne gracza
	
	while((ent = find_ent_in_sphere(-1, fOrigin, 200.0)) != 0) 
	{
                   new x[33]
                   pev(ent,pev_classname,x)
		if(equal(x,"Twoja_Nazwa"))
                {
                remove_entity(ent)
                }
	}
}

  • +
  • -
  • 1


#675787 PAWN Pre-Processor Część 1

Napisane przez DarkGL w 19.12.2014 12:11

Jest to pierwsza część cyklu tutoriali na temat preprocesora autorstwa Y_Less przetłumaczona na język polski
Źródło http://forum.sa-mp.c...5175#post785175

 

http://darkgl.amxx.p...cessor-czesc-1/

Sam tutorial dotyczy preprocesora obecnego w wersji pawn'a dla sa:mp jednak wiele rzeczy jest wspólnych , niektóre niestety działają tylko w sa:mp ale postanowiłem zostawić ich opis jaką ciekawostkę. Wszelkie uwagi co do tlumaczenia mile widziane. Podczas tłumaczenia dodawałem / zmieniałem rzeczy od siebie.
Za wszystkie błędy lub nieścisłości przepraszam czasami ciężko było przenieść znaczenie zdań z języka angielskiego na polski.

Zawartość

Część 1 - Obejmuje wprowadzenie do preprocesora oraz kilka ważnych rzeczy przydatnych podczas pisania makr.
Część 2 - Wyjaśnienie dokładnie czego szuka kompilator oraz typowych zastosowań makr.
Część 3 - Opis innych dostępnych dyrektyw (oprócz"#define") oraz spojrzenie na definicje bez wartości podmiany.
Część 4 - Używanie stringów w preprocesorze.
Część 5 - Alternatywy dla preprocesora, wiele symboli i rekurencja.
Część 6 - Problemy z makrami oraz spacje.

Podstawowa podmiana

Na początek proste makra i jeszcze prostsze definicje. Idealny początek do wprowadzenia jak działa preprocesor.

Definicje

Definicja poniżej składa się tylko z tekstu do podmiany i tekstu na który podmieniasz.
 

#define MAX_PLAYERS                     500

Klasyka - definicja określa ilośc graczy na Twoim serwerze.Idealny przykład jak działają definicje. Preprocesor jak sama nazwa wskazuje wykonuje się przed głownym procesem ( kompilatorem ). Kompilator bierze napisany kod i konwertuje go do pliku AMXX, preprocesor generuje napisany kod. Przykład:
 

printf("%d", MAX_PLAYERS);

Preprocesor podczas wykonywania przekonwertuje ten kod do:
 

printf("%d", 500);

Jest to kod który zostanie przekazany głownemu kompilatorowi i to ten kod zostanie przekonwertowany do pliku wynikowego ( AMXX ). Jest to po prostu podmiana tekstu. Wszystkie makra są w tej samej formie:
 

#define <szukany text><spacja/spacje><text podmiany>

Warto zauważyć że spacja jest ważna - pierwsza spacja oznacza koniec stringu który będzie szukany, wszystko za spacją jest traktowane jako string na który preprocesor będzie podmieniał znalezione stringi! W przykładzie wyżej szukany string to "MAX_PLAYERS" a string podmiany to "500".

Makra

Makro to coś w rodzaju funkcji - posiada parametry. Nazwy parametrów zaczynają się od "%0" do "%9" ( "%0" , "%1" , "%2" itp. itd. ) - nie można im nadać własnych nazw. Funkcja zwracająca maksymalną ilośc graczy pomnożoną przez liczbę wyglądała by tak:
 

MaxPlayersTimesNumber(number)
{
    return MAX_PLAYERS * number;
    // Pamiętaj że "MAX_PLAYERS" jest definicją więc kompilator skompiluje te wyrażenie jako:
    //  return (500) * number;
}

Makro robiące to samo wyglądało by tak:
 

#define MAX_PLAYERS_TIMES_NUMBER(%0)    MAX_PLAYERS * %0

Tym razem szukanym stringiem jest "MAX_PLAYERS_TIMES_NUMBER(%0)" a stringiem podmiany jest "MAX_PLAYERS * %0". "%0" to specjalne wyrażenie - nie oznacza szukaj "%0", oznacza szukaj czegokolwiek pomiędzy dwoma nawiasami . "%0" otrzymują tą samą wartość która była pomiędzy nawiasami w stringu który był podmieniany.
Przykład:
 

#define MAX_PLAYERS                     500
#define MAX_PLAYERS_TIMES_NUMBER(%0)    MAX_PLAYERS * %0

printf("%d", MAX_PLAYERS_TIMES_NUMBER(7));

Po wykonaniu preprocesora ( podamiana "%0" na "7" ) otrzymujemy:
 

#define MAX_PLAYERS                     500

printf("%d", MAX_PLAYERS * 7);

"MAX_PLAYERS" jest dodatkowo makrem więc otrzymujemy:
 

printf("%d", 500 * 7);

Warto zauwayżyć że kompilator jest "inteligentny" - jeśli widzi takie wyrażenie jak to tutaj gdzie nie mamy żadnych zmiennych , wyliczy sobie wartość , więc kod który finalnie dostajemy do kompilacji wygląda tak ( kompilator nie umie formatować stringów ):
 

printf("%d", 3500);

Można by to też zrobić tak:
 

#define MAX_PLAYERS                     500
#define MAX_PLAYERS_TIMES_NUMBER(%0)    MAX_PLAYERS * %0

new value = 7;
printf("%d", MAX_PLAYERS_TIMES_NUMBER(value));

Po wykonaniu preprocesora ( podamiana "%0" na "value" ) otrzymujemy:
 

#define MAX_PLAYERS                     500

new value = 7;
printf("%d", MAX_PLAYERS * value);

"MAX_PLAYERS" jest makrem więc otrzymujemy:
 

new value = 7;
printf("%d", 500 * value);

Ponieważ te wyrażenie używa zmiennej kompilator nie umie go wyliczyć. Więc jest to finalny kod który zostaje skompilowany.

Dlaczego ?

Więc dlaczego używać makr zamiast funkcji ( lub dlaczego używać funkcji zamiast makr )? Makra podmieniają tekst - więc wszedzie gdzie umieścisz makro tam zostanie dodany twój tekst. Jeśli masz makro w kodzie użyte 100 razy , kod zostanie wygenerowany 100 razy. Z drugiej strony jeśli masz 100 wywołań funkcji w swoim kodzie , kod zostanie dodany tylko raz mimo 100 wywołań. Funkcje są prawdopodbnie bardziej użyteczne jeśli masz dużo kodu - duże bloki kodu występujące 100 razy utworzą bardzo duży plik AMXX ! Makra są raczej używane przy małej ilości kodu - wywołanie funkcji zajmuje pamieć i czas procesora więc jeśli masz mały blok kodu nie opłaca się wywoływać funkcji , ale to nie jest zasadą ! Jeśli użyłbyś funkcji zamiast makra powyżej , skompilowany kod wygląał by tak:
 

MaxPlayersTimesNumber(number)
{
    return (500) * number;
}

Przykład 1:
 

printf("%d", MaxPlayersTimesNumber(7));

Przykład 2:
 

new value = 7;
printf("%d", MaxPlayersTimesNumber(value));

W obu przypadkach kompilator nie wie jak zoptymalizować kod.

Konwencja

Jedną z rzeczy które mogłeś zauważyć czytając ten poradnik jest nazewnictwo ,funkcja została nazwana "MaxPlayersTimesNumber" to samo makro zostało nazwane "MAX_PLAYERS_TIMES_NUMBER".
To tylko konwencja - funkcje w tym poradnik będą miały nazwy pisane małymi literami oprócz pierwszych znaków wyrazów , makra za to będą miały nazwy pisane wielkimi literami z wyrazami oddzielonymi "_", jest to po to,aby łatwo można było zorientować się czego teraz używamy bez sprawdzania definicji.

Kolejna konwencja to ustawianie stringu podmiany na pozycji 40 ( kiedy to możliwe ) - jest to po to, aby ułatwić czytanie dużej ilości makr np.
 

#define DEFINITION_1                    1
#define MY_DEF                          2
#define SOME_OTHER_LONG_NAME_DEFINITION 3
#define A_MACRO(%0)                     3 * %0

Zamiast:
 

#define DEFINITION_1 1
#define MY_DEF 2
#define SOME_OTHER_LONG_NAME_DEFINITION 3
#define A_MACRO(%0) 3 * %0

Żadna z tych konwencji nie jest zasadą, więc masz wolną ręke przy używaniu ich, jeśli chcesz możesz je zignorować. Ale zachęcał bym Cie to posiadania naprawdę dobrych powodów zanim je zignorujesz.

Składnia / Semantyka

Szybkie przypomnienie. "Składnia" jest to wygląd kodu, "Semantyka" oznacza to co ten kod robi . Składnia pętli for to: "for (; ; ) {}", "semantyka" pętli for to: wykonaj się ileś razy na podstawie przekazanych parametrów. Wążna sprawą w następnej sekcji jest składnia i semantyka funkcji "printf". Składnia to: "printf(string[], ...);" - czyli string a następnie dowolna ilość parametrów, zawartość stringu nie wpływa na składnie - "printf("%d", 6, 7);" spełnia zasady składnie, ale 7 nie zostanie wyświetlona ponieważ string określa semantykę funkcji ( co ona naprawdę robi ).Kod się skompiluje ale nie będzie działał poprawnie , i jest to bardzo ważna różnica.

Parametry

Makro może posiadać kilka parametrów:
 

#define MULTIPLY_TWO_NUMBERS(%0,%1)     %0 * %1

W rzeczywistości makro może mieć nawet do 10 parametrów:
 

#define MULTIPLY_NUMBERS(%0,%1,%2,%3,%4,%5,%6,%7,%8,%9) %0 * %1 * %2 * %3 * %4 * %5 * %6 * %7 * %8 * %9

Niektórzy lubią stawiać spacje po przecinku w liście parametrów np.:
 

#define MULTIPLY_TWO_NUMBERS(%0, %1)     %0 * %1

Czegoś takiego nie można robić w makrach - tak jak było wcześniej powiedziane spacja oznacza koniec stringu do podmiany , więc preprocesor będzie szukał "MULTIPLY_TWO_NUMBERS(%0,", a nie "MULTIPLY_TWO_NUMBERS(%0, %1)" i podmieni to na "%1) %0 * %1".

Teraz kiedy wiesz już czym jest makro i czym są jego parametry możemy skupić się na różnicach parametrów makr i parametrów funkcji.

Po pierwsze - parametry makra i funkcji nie są tym samym i nie powinny być traktowane w ten sam sposób. Parametry funkcji są oddzielane przecinkami, parametry makr są oddzielone czymkolwiek chcesz.

Ten kod nie jest poprawny, podczas wywołania funkcji jest przekazywane za dużo parametrów:
 

MyFunc(a)
{
    return a;
}

main()
{
    printf("%d", MyFunc(1, 2));
}

Ten kod jest poprawny:
 

#define MY_FUNC(%0)                     %0

main()
{
    printf("%d", MY_FUNC(1, 2));
}

W przykładzie wyżej makro "MY_FUNC" szuka czegoś pomiędzy dwoma nawiasami poprzedzone "MY_FUNC". W tym przykładzie zawartością pomiędzy nawiasami jest "1, 2". Wyrażenie zawiera przecinek ale dla makra nie robi to różnicy. Kod po wykonynaniu preprocesora dla tego makra będzie wyglądał tak:
 

main()
{
    printf("%d", 1, 2);
}

Wygenerowany kod jest w pełni poprawny( oczywiście 2 nie zostanie wyświetlone ).

Jeśli parametry nie są odzielane przecinkami , jak móc używać więcej niż jednego ? Parametry są odzielane czymkolwiek chcesz żeby były odzielane np.:
 

#define MULTIPLY_TWO_NUMBERS(%0,%1)     %0 * %1

Kod wyżej będzie szukał "MULTIPLY_TWO_NUMBERS(" następnie wszystkiego do przecinka , przecinka , wszystkiego do zamykającego nawiasu.
 

printf("%d", MULTIPLY_TWO_NUMBERS(6, 7));

Kod wyżej zostanie podmieniony przez makro ( spacja tutaj jest dopuszczalna , nie jest dopuszczalna w deklaracji ) i otrzymamy taki kod:
 

printf("%d", 6 * 7);

Jednak przecinek nie jest zamykajacym nawiasem więc to też jest prawidłowe:
 

printf("%d", MULTIPLY_TWO_NUMBERS(6, 7, 8));

W tym przypadku parametr "%0" przyjmuje wartość 6 a parametr "%1" przyjmuje wartość "7,8" więc po wygenerowaniu kodu otrzymamy:
 

printf("%d", 6 * 7, 8);

Nawiasy

Skoro parametry są tak elastyczne jak możemy kontrolować to co generuje nam preprocesor ? Wszystkie makra wyżej były bardzo złe , nie używały nawiasów.

Przykład:






// Without brackets (first).
#define MULTIPLY_TWO_A(%0,%1)           %0 * %1

// With brackets (second).
#define MULTIPLY_TWO_B(%0,%1)           ((%0) * (%1))

main()
{
    // Two with first.
    printf("%d", MULTIPLY_TWO_A(6, 7));
    
    // Two with second.
    printf("%d", MULTIPLY_TWO_B(6, 7));
    
    // Three with first.
    printf("%d", MULTIPLY_TWO_A(6, 7, 8));
    
    // Three with second.
    printf("%d", MULTIPLY_TWO_B(6, 7, 8));
}

Po wygenerowaniu otrzymamy taki kod:
 

main()
{
    // VALID
    printf("%d", 6 * 7);
    
    // VALID
    printf("%d", ((6) * (7)));
    
    // VALID
    printf("%d", 6 * 7, 8));
    
    // INVALID!
    printf("%d", ((6) * (7, 8)));
}

Finalny kod pokazuje ważna różnice , po dodaniu nawiasów wygenerowany kod jest błędny ( składnia jest błędna ). Próbujemy mnożyć "6" przez "7,8" - co jest błędne więc użytkownik dostanie błąd przy kompilacji.

Inne użycie nawiasów to ustalanie priorytetów operatorów. Dzięki nawiasom możemy ustalać kolejność wykonywania operatorów np. "4 + 5 * 6" otrzymujemy "34", nie "54". Ponieważ * ma wyższy priorytet niż + więc "4 + 5 * 6" zostaje wykonane do "4 + 30" a potem "34". Jeśli parametry były by wykonywane po kolei "4 + 5 * 6" staje się "9 * 6" a następnie "54".

Przeanalizujmy taki kod
 

#define ADD_TWO(%0,%1)                  %0 + %1

main()
{
    printf("%d", ADD_TWO(3, 3) * 7);
}

3 + 3 to 6 , 6 * 7 to 42 prawda? Nie! Zobaczmy wygenerowany kod.
 

main()
{
    printf("%d", 3 + 3 * 7);
}

Wiemy co się stanie, mnożenie zostanie wykonane przed dodawaniem więc otrzymamy 24. Całość możemy naprawić dodając nawiasy:
 

#define ADD_TWO(%0,%1)                  (%0 + %1)

Kolejny przykład
 

#define MUL_TWO(%0,%1)                  (%0 * %1)

main()
{
    printf("%d", MUL_TWO(3 + 3, 7));
}

Dodaliśmy nawiasy więc wszystko powinno być ok ? Błąd ! Zobaczmy co wygenerował preprocesor:
 

main()
{
    printf("%d", (3 + 3 * 7));
}

Obliczenia są w nawiasach, ale znowu mnożenie zostanie wykonane przed dodawaniem. Powinniśmy dodać jeszcze jeden poziom nawiasów dzięki czemu wszystkie operacje będa wykonywane poprawnie:
 

#define MUL_TWO(%0,%1)                  ((%0) * (%1))

PAMIĘTAJ: Owijaj makro i parametry makra w nawiasy. Istnieją sytuację kiedy nie trzeba tego robić ale o nich opowiem później.

Makra kilku linijkowe

Makro może mieć kilka linii dzięki użyciu "\". Zasada jest prosta jeśli na końcu linii znajduje się znak \ makro jest kontynuowane w kolejnej linii. Makro nie może być kontynuowane w parametrach i nazwie z tych samych powodów z których nie możemy używać spacji. Uwaga: W tym poradniku znak kontynuacji jest umieszczany na pozycji 80:
 

#define MUL_TWO(%0,%1)                                                          \
    ((%0) * (%1))
#define MUL_TWO(%0,%1)                                                          \
    (                                                                           \
        (%0)                                                                    \
        *                                                                       \
        (%1)                                                                    \
    )
#define MUL_TWO(%0,%1)                                                          \
    (                                                                           \
        (                                                                       \
            %0                                                                  \
        )                                                                       \
        *                                                                       \
        (                                                                       \
            %1                                                                  \
        )                                                                       \
    )

Ostatnia linii makra nie posiada operatora konytnuacji.

Pułapka

Jest jeden bardzo ważny problem podczas używania makr zamiast funkcji:

Wersja funkcyjna:
 

PrintSquare(var)
{
    printf("%d", var * var);
}

main()
{
    new
        var = 2;
    PrintSquare(var++);
    printf("%d", var);
}

Wynik:
4
3

Wersja z makrami:
 

#define PRINT_SQUARE(%0)                printf("%d", (%0) * (%0))

main()
{
    new
        var = 2;
    PRINT_SQUARE(var++);
    printf("%d", var);
}

Możemy otrzymać:
4
4

Lub:
6
4

Ponieważ parametry przekazane do makra są inkrementowane , więc inkrementacja jest dodawana przy generowaniu kodu:
 

main()
{
    new
        var = 2;
    printf("%d", (var++) * (var++));
    printf("%d", var);
}

W takim przypadku w drugim printf zmienna var będzie zinkrementowana dwa razy - co jest błędne i nie wydarzy sie podczas użycia funkcji.

Kolejność wykonania dla operatora inkrementowania może zostać wykonana na dwa sposoby:
 

temp1 = var;
temp2 = var;
var   = var + 1;
var   = var + 1;
printf("%d", temp1 * temp2);

Lub:
 

temp1 = var;
var   = var + 1;
temp2 = var;
var   = var + 1;
printf("%d", temp1 * temp2);

Oba są technicznie prawidłowe - w obu przypadkach inkrementowanie jest wykonane po użyciu zmiennej , problemem jest tylko który sposób wybierze kompilator. Dlatego wynik może być "4" lub "6".

Bądź bardzo uważny podczas używania makr z parametrami które modyfikują zmienne - dlatego nazwy makr są pisane bardzo często z dużych liter aby użytkownik wiedział że jest to makro i był bardzo uważny podczas jego używania.


  • +
  • -
  • 12


#673475 Dwa razy plugin_precache

Napisane przez GwynBleidD w 04.12.2014 10:51

Rozwinę to, co darkgl napisał: w include tworzysz normalnie plugin_precache, a na jego końcu (lub początku, jeśli wolisz) wykonujesz dowolną funkcję poprzez callfunc (aby nie wysypywało błędów, gdy funkcja nie istnieje). Poniżej plugin_precache w include aliasujesz plugin_precache na swoją funkcję, dzięki czemu w kodzie w pluginie znów możesz użyć plugin_precache. Sposób dość sprytny :)


  • +
  • -
  • 3


#673428 Dwa razy plugin_precache

Napisane przez DarkGL w 04.12.2014 06:50

Coś w stylu http://darkgl.amxx.p...ania-configami/ ?
  • +
  • -
  • 3