Pular para o conteúdo principal

Diretivas

As diretivas são instruções passadas ao compilador para controlar como ele interpreta seu código fonte.

#assert

Isto verifica se a expressão constante é verdadeira e se não aborta a compilação.

#define MOO 10
#assert MOO > 5

Isso irá compilar corretamente.

#define MOO 1
#assert MOO > 5

Isso não vai dar e dará um erro fatal. Isto é semelhante a:

#define MOO 1
#if MOO <= 5
#error MOO check failed
#endif

No entanto, a afirmação dará um erro:

Assertation failed: 1 > 5

Onde o segundo dará um erro:

User error: Moo check failed

O que pode ou não ser útil.

#define

#define é uma diretiva de substituição de texto, onde quer que o primeiro símbolo da definição seja encontrado, o resto será colocado.

#define MOO 7
printf("%d", MOO);

Será mudado para:

printf("%d", 7);

É por isso que todas as definições se perdem na descompilação, pois não existem quando o código é compilado (todas as diretivas são pré-processadas). As definições não têm que conter números:

#define PL new i = 0; i < MAX_PLAYERS; i++) if (IsPlayerConnected(i)

for(PL) printf("%d connected", i);

Compilará para o loop de 1000, mais conhecido como Player Loop que todos nós conhecemos e amamos(e desprezamos). Observe como os parênteses são usados aqui, alguns do loop 'for' e outros do macro definido (o substituto).

Outro fato pouco conhecido sobre as definições é que elas podem ser multi-linhas se você pular da nova linha. Geralmente uma nova linha termina a definição, no entanto, o seguinte é válido:

#define PL \
new i = 0; i < MAX_PLAYERS; i++) \
if (IsPlayerConnected(i)

printf("%d", MOO(6));

Isso resultará em 42 (não, não é escolhido aleatoriamente). Notou os parênteses excessivos na definição? Isto porque as definições são substituições de texto reto, de modo que serão compiladas como:

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

Está bem assim, mas olhe este exemplo:

printf("%d", MOO(5 + 6));

Você esperaria que compilasse para produzir 77 ((5 + 6) * 7) e com os parênteses, porém sem os parênteses que você tem:

#define MOO(%0) \
%0 * 7

printf("%d", MOO(5 + 6));

O que converte para:

printf("%d", MOO(5 + 6 * 7));

Que, devido à ordem de operações, compila como (5 + (6 * 7)), o que se for 47 e é muito errado.

Um fato interessante sobre os parâmetros é que, se você tem muitos, o último será todos os parâmetros extras. Assim formando:

#define PP(%0,%1) \
printf(%0, %1)

PP(%s %s %s, "hi", "hello", "hi");

Irá imprimir de fato:

hi hello hi

Como %1 contém "hi", "hello", "hi". Você também deve ter notado o uso de # para converter um literal em uma string. Esta é uma característica apenas do SA-MP e pode ser útil. Foi apenas adicionado aqui para dar uma distinta distinção entre os parâmetros.

#else

#else É igual ao else comum, só que na diretiva #else.

#elseif

#elseif É igual elseif comum, só que na diretiva #if.

#define MOO 10

#if MOO == 9
printf("if");
#elseif MOO == 8
printf("else if");
#else
printf("else");
#endif

#emit

Esta diretiva não está listada na tabela pawn-lang.pdf, entretanto, ela existe. Ela é basicamente um compilador em linha. Se você conhece AMX, você pode usar isto para colocar os opcodes AMX diretamente em seu código. A única limitação é que isso permite apenas um argumento. Sintaxe: #emita <opcódigo>>argumento>. <argumento> pode ser um número racional, inteiro ou símbolo (local ou global) (variáveis, funções e rótulos). A lista de opcodes e seu significado pode ser encontrada em Pawn Toolkit ver. 3664.

#endif

#endif É como se um aparelho para-se. #if não usar aparelho, tudo é somado condicionalmente até o correspondente #endif.

#endinput, #endscript

Isto impede a inclusão de um único arquivo.

#error

Isto serve para o compilador instantaneamente imprimir mensagem de erro personalizada. Veja #assert para um exemplo.

#if

#if Indica para o pré-processador e se é para compilar aquele trecho de código. Pode escolher exatamente o que compilar e o que não compilar a partir daqui. Por exemplo, considere o seguinte código:

#define LIMITE 10

if (LIMITE < 10)
{
printf("Limite muito baixo");
}

That will compile as:

if (10 < 10)
{
printf("Limite muito baixo");
}

O que claramente nunca retornará verdadeiro e o compilador sabe disso - portanto retornará um aviso de "expressão constante". A questão é, se nunca será verdade, de que vale a pena incluí-lo de todo? Poderá simplesmente remover o código, mas depois não haverá verificações se alguém alterar o macro LIMITE e recompilar. É para isto que serve a diretiva #if. Ao contrário do normal, que dá um aviso se a expressão for constante, as expressões #if devem ser constantes. Portanto:

#define LIMITE 10

#if LIMITE < 10
#error Limite muito baixo
#endif

Isso irá verificar que o limite não é demasiado pequeno quando se compila e se é, dará um erro de tempo de compilação, em vez de se ter de testar o modo para ver se há algo de errado. Isto também significa que não é gerado um excesso de código. Note também a falta de parênteses, pode utilizá-los, e pode precisar deles em expressões mais complexas, mas não são necessários.

Aqui está outro exemplo:

#define LIMITE 10

if (LIMITE < 10)
{
printf("Limite menor que 10");
}
else
{
printf("Limite igual ou menor do que 10");
}

Mais uma vez, esta é uma verificação constante, que dará um aviso, mas ambas as impressões serão compiladas quando sabermos que apenas uma será executada. Usando #if isto se tornar:

#define LIMITE 10

#if LIMITE < 10
printf("Limite menor que 10");
#else
printf("Limite igual ou menor que 10");
#endif

Dessa forma, apenas a impressão que é necessária será compilada e a outra ainda estará no seu código-fonte, caso alterem o valor do macro LIMITE e recompilem, mas não será incluída no código, uma vez que não é necessária. Esta forma também significa o inútil se não for executado sempre que o seu código for executado, o que é sempre bom.

#include

Isto retira todo o código de um arquivo especificado e insere-o no seu código no ponto em que a linha include se encontra. Há dois tipos de include: relativo e sistema (termos inventados pelo autor para simplificar o que está sendo feito). Relativo inclui usar aspas duplas em torno do nome do arquivo e estão localizados em relação ao arquivo atual, portanto:

#include "include.pwn"

incluiria o arquivo "include.pwn" do mesmo diretório que o arquivo incluindo esse arquivo. O outro tipo, sistema, inclui o arquivo do diretório "include" que está localizado ou no mesmo diretório que o compilador Pawn ou diretório pai (caminhos: "include",".../include"):

#include "<include>"

Incluiria o arquivo "include.inc" (note a falta de extensão, pode especificar se um arquivo não for .p (não .pwn ou .inc) do diretório pawno/include (supondo que você esteja utilizando Pawno).

Ambos os tipos podem conter diretórios:

#include <diretorio/include>

Ambos incluirão um arquivo de um diretório abaixo dos respectivos directórios por defeito. Se o arquivo não existir, a compilação falhará.

#pragma

Esta é uma das diretivas mais complexas. Ela tem uma série de opções para controlar como seu roteiro funciona. Um exemplo de configuração pareceria:

#pragma ctrlchar '$'

Mais uma vez, esta é uma verificação constante, que dará um aviso, mas ambas as impressões serão compiladas quando sabermos que apenas uma será executada. Usando #if isto se tornar:

NomeValoresDescrição
codepagenome/valorDefine a página de codificação Unicode a utilizar para cordas.
comprimir1/0Sem suporte no SA-MP - não tente usá-lo.
depreciadosímbologerou um aviso se o símbolo dado for utilizado para dizer às pessoas que há uma versão melhor disponível.
dinâmicovalor (geralmente uma potência de 2)Define o tamanho da memória (em células) atribuída à pilha e à pilha. Necessário se receber um aviso de utilização de memória em excesso após a compilação. (Uma tabela estranha após a linha de copyright do compilador)
bibliotecanome dllWidley incorrectamente utilizado no SA-MP. Isto especifica a dll para obter as funções nativas definidas no ficheiro de onde é proveniente. Não define um ficheiro como uma biblioteca.
pack1/0Troque os significados de !"" e """. Ver penhor-lang.pdf para mais informações sobre cordas embaladas.
tamanho do separadorvalorOutra configuração largamente mal utilizada. Isto deve ser utilizado para definir o tamanho de um separador para evitar avisos de compilação que estejam errados devido a espaços e separadores serem utilizados alternadamente. Isto é definido para 4 em SA:MP, pois é o tamanho de uma tabulação em pawno. Definindo este valor como 0 irá suprimir todos os seus avisos de indentação, mas é altamente desaconselhável uma vez que permite um código totalmente ilegível.
não utilizadosímbolocomo depreciado isto aparece após o símbolo para o qual se deseja suprimir o aviso "símbolo nunca é utilizado". Geralmente, o método preferido para o fazer é a utilização de stock, no entanto, isto nem sempre é aplicável (por exemplo, os parâmetros da função não podem ser compilados).

Descontinuado

new
gOldVariable = 5;

#pragma deprecated gOldVariable

main() {printf("%d", gOldVariable);}

Isso dará um aviso de que a gOldVariable não deve mais ser usada. Isto é útil principalmente para funções que preservam a compatibilidade com o passado enquanto atualizam o API.

#tryinclude

Isso é semelhante a #include, mas se o arquivo não existir, a compilação não falhará. Isso é útil apenas para incluir recursos em seu script se uma pessoa tiver o plugin correto instalado(Ou pelo menos o plugin incluído)

myinc.inc

#if defined _MY_INC_INC
#endinput
#endif
#define _MY_INC_INC

stock MinhaIncludeFunc() {printf("Olá!");}

Gamemode:

#tryinclude <minhainc>

main()
{
#if defined _MINHA_INC_INC
MinhaIncludeFunc();
#endif
}

Isso só chamará a função MinhaIncludeFunc se o arquivo com ele for encontrado na pasta includes e compilado com sucesso. Isso, como afirmado anteriormente, é bom para plugins padrões (Por exemplo a_samp.inc ou a_actors.inc) para verificar se o desenvolvedor realmente tem o plugin instalado.

#undef

Remove um macro ou simbolo constante anteriormente definido.

#define MOO 10
printf("%d", MOO);
#undef MOO
printf("%d", MOO);

Irá falhar ao compilar, pois o macro MOO não existe.

enum {
e_example = 300
};

printf("%d", e_example);
#undef e_example
printf("%d", e_example); // fatal error