|
| 1 | +--- |
| 2 | +title: "Palavras-chave: inicializadores" |
| 3 | +sidebar_label: "Palavras-chave: inicializadores" |
| 4 | +--- |
| 5 | + |
| 6 | +## `const` |
| 7 | + |
| 8 | +```c |
| 9 | +new const |
| 10 | + MY_CONSTANT[] = {1, 2, 3}; |
| 11 | +``` |
| 12 | +
|
| 13 | +`const` não é muito usado, mas serve para declarar variáveis que não podem ser alteradas em tempo de execução. Em funções, parâmetros de array marcados como `const` podem ser otimizados, e você pode criar algo parecido com um `#define`, só que baseado em arrays. Como `const` é um modificador, ele deve acompanhar `new` ou outro declarador de variável. Se tentar modificar uma variável constante, o compilador reclamará. |
| 14 | +
|
| 15 | +## `enum` |
| 16 | +
|
| 17 | +Enums são úteis para agrupar dados relacionados, substituir longas listas de `#define`s e criar novas tags. Também facilitam o controle de índices de arrays. |
| 18 | +
|
| 19 | +Definição mais comum: |
| 20 | +
|
| 21 | +```c |
| 22 | +enum E_MY_ARRAY |
| 23 | +{ |
| 24 | + E_MY_ARRAY_MONEY, |
| 25 | + E_MY_ARRAY_GUN |
| 26 | +} |
| 27 | +
|
| 28 | +new |
| 29 | + gPlayerData[MAX_PLAYERS][E_MY_ARRAY]; |
| 30 | +
|
| 31 | +public OnPlayerConnect(playerid) |
| 32 | +{ |
| 33 | + gPlayerData[playerid][E_MY_ARRAY_MONEY] = 0; |
| 34 | + gPlayerData[playerid][E_MY_ARRAY_GUN] = 5; |
| 35 | +} |
| 36 | +``` |
| 37 | + |
| 38 | +Isso cria dois slots por jogador. Sem enum, ficaria: |
| 39 | + |
| 40 | +```c |
| 41 | +new |
| 42 | + gPlayerData[MAX_PLAYERS][2]; |
| 43 | + |
| 44 | +public OnPlayerConnect(playerid) |
| 45 | +{ |
| 46 | + gPlayerData[playerid][0] = 0; |
| 47 | + gPlayerData[playerid][1] = 5; |
| 48 | +} |
| 49 | +``` |
| 50 | +
|
| 51 | +Funciona, mas é menos legível. Se quiser inserir um slot entre 0 e 1, teria de renumerar tudo. Com enum basta adicionar o novo campo: |
| 52 | +
|
| 53 | +```c |
| 54 | +enum E_MY_ARRAY |
| 55 | +{ |
| 56 | + E_MY_ARRAY_MONEY, |
| 57 | + E_MY_ARRAY_AMMO, |
| 58 | + E_MY_ARRAY_GUN |
| 59 | +} |
| 60 | +``` |
| 61 | + |
| 62 | +Ao recompilar, o compilador ajusta todos os índices. |
| 63 | + |
| 64 | +A forma completa de um enum é: |
| 65 | + |
| 66 | +```c |
| 67 | +enum NAME (modificador) |
| 68 | +{ |
| 69 | + NAME_ENTRY_1 = valor, |
| 70 | + ... |
| 71 | +} |
| 72 | +``` |
| 73 | +
|
| 74 | +Se você não definir um modificador, o padrão é `+= 1`. Ou seja, cada item vale o item anterior + 1. Exemplo: |
| 75 | +
|
| 76 | +```c |
| 77 | +enum E_EXAMPLE |
| 78 | +{ |
| 79 | + E_EXAMPLE_0, |
| 80 | + E_EXAMPLE_1, |
| 81 | + E_EXAMPLE_2 |
| 82 | +} |
| 83 | +``` |
| 84 | + |
| 85 | +Aqui temos 0, 1, 2 e o valor do enum (`E_EXAMPLE`) é 3. Mudando o modificador para `+= 5` os valores passam a ser 0, 5, 10 e 15. Declarar um array com `gEnumArray[E_EXAMPLE]` reservá 15 células, mas os índices simbólicos atingem apenas 0, 5 e 10. |
| 86 | + |
| 87 | +Também é possível usar outro modificador, como `*= 2`. Nesse caso, se não definir o primeiro valor manualmente, todos continuam 0. Para corrigir, basta atribuir um valor inicial: |
| 88 | + |
| 89 | +```c |
| 90 | +enum E_EXAMPLE (*= 2) |
| 91 | +{ |
| 92 | + E_EXAMPLE_0 = 1, |
| 93 | + E_EXAMPLE_1, |
| 94 | + E_EXAMPLE_2 |
| 95 | +} |
| 96 | +``` |
| 97 | +
|
| 98 | +Resultado: 1, 2, 4 e 8. Você pode definir quantos valores quiser: |
| 99 | +
|
| 100 | +```c |
| 101 | +enum E_EXAMPLE (*= 2) |
| 102 | +{ |
| 103 | + E_EXAMPLE_0, |
| 104 | + E_EXAMPLE_1 = 1, |
| 105 | + E_EXAMPLE_2 |
| 106 | +} // 0, 1, 2, 4 |
| 107 | +``` |
| 108 | + |
| 109 | +Arrays também são suportados: |
| 110 | + |
| 111 | +```c |
| 112 | +enum E_EXAMPLE |
| 113 | +{ |
| 114 | + E_EXAMPLE_0[10], |
| 115 | + E_EXAMPLE_1, |
| 116 | + E_EXAMPLE_2 |
| 117 | +} // produz 0, 10, 11 e 12 |
| 118 | +``` |
| 119 | + |
| 120 | +Itens podem ter tags. No exemplo inicial: |
| 121 | + |
| 122 | +```c |
| 123 | +enum E_MY_ARRAY |
| 124 | +{ |
| 125 | + E_MY_ARRAY_MONEY, |
| 126 | + E_MY_ARRAY_AMMO, |
| 127 | + Float:E_MY_ARRAY_HEALTH, |
| 128 | + E_MY_ARRAY_GUN |
| 129 | +} |
| 130 | +``` |
| 131 | + |
| 132 | +Assim evitamos `tag mismatch` ao armazenar floats. |
| 133 | + |
| 134 | +Enums também podem servir como tags: |
| 135 | + |
| 136 | +```c |
| 137 | +enum E_MY_TAG (<<= 1) |
| 138 | +{ |
| 139 | + E_MY_TAG_NONE, |
| 140 | + E_MY_TAG_VAL_1 = 1, |
| 141 | + E_MY_TAG_VAL_2, |
| 142 | + E_MY_TAG_VAL_3, |
| 143 | + E_MY_TAG_VAL_4 |
| 144 | +} |
| 145 | + |
| 146 | +new |
| 147 | + E_MY_TAG:gMyTagVar = E_MY_TAG_VAL_2 | E_MY_TAG_VAL_3; |
| 148 | +``` |
| 149 | +
|
| 150 | +`gMyTagVar` terá valor 6 e tag personalizada. Atribuir um número puro gera aviso: |
| 151 | +
|
| 152 | +```c |
| 153 | +gMyTagVar = 7; // warning |
| 154 | +gMyTagVar = E_MY_TAG:7; // válido |
| 155 | +``` |
| 156 | + |
| 157 | +Muito útil para flags ou dados combinados: |
| 158 | + |
| 159 | +```c |
| 160 | +enum E_MY_TAG (<<= 1) |
| 161 | +{ |
| 162 | + E_MY_TAG_NONE, |
| 163 | + E_MY_TAG_MASK = 0xFF, |
| 164 | + E_MY_TAG_VAL_1 = 0x100, |
| 165 | + E_MY_TAG_VAL_2, |
| 166 | + E_MY_TAG_VAL_3, |
| 167 | + E_MY_TAG_VAL_4 |
| 168 | +} |
| 169 | + |
| 170 | +new |
| 171 | + E_MY_TAG:gMyTagVar = E_MY_TAG_VAL_2 | E_MY_TAG_VAL_3 | (E_MY_TAG:7 & E_MY_TAG_MASK); |
| 172 | +``` |
| 173 | +
|
| 174 | +Valor final: 0x0607 (1543). |
| 175 | +
|
| 176 | +Enums também podem substituir blocos de `#define`: |
| 177 | +
|
| 178 | +```c |
| 179 | +enum |
| 180 | +{ |
| 181 | + TEAM_NONE, |
| 182 | + TEAM_COP, |
| 183 | + TEAM_ROBBER, |
| 184 | + TEAM_CIV, |
| 185 | + TEAM_CLERK, |
| 186 | + TEAM_DRIVER |
| 187 | +} |
| 188 | +``` |
| 189 | + |
| 190 | +Os valores continuam 0–5 e o uso é idêntico. Você pode ainda transformá-los em bitmasks para permitir múltiplos times: |
| 191 | + |
| 192 | +```c |
| 193 | +enum (<<= 1) |
| 194 | +{ |
| 195 | + TEAM_NONE, |
| 196 | + TEAM_COP = 1, |
| 197 | + TEAM_ROBBER, |
| 198 | + TEAM_CIV, |
| 199 | + TEAM_CLERK, |
| 200 | + TEAM_DRIVER, |
| 201 | + TEAM_ADMIN |
| 202 | +} |
| 203 | +``` |
| 204 | + |
| 205 | +Operações básicas: |
| 206 | + |
| 207 | +- Adicionar: `gPlayerTeam[playerid] |= TEAM_COP` |
| 208 | +- Remover: `gPlayerTeam[playerid] &= ~TEAM_COP` |
| 209 | +- Verificar: `if (gPlayerTeam[playerid] & TEAM_COP)` |
| 210 | + |
| 211 | +## `forward` |
| 212 | + |
| 213 | +Informa ao compilador que uma função será declarada depois. Obrigatório para todas as `public`, mas útil em outros casos, como funções que retornam tags. |
| 214 | + |
| 215 | +```c |
| 216 | +forward MyPublicFunction(playerid, const string[]); |
| 217 | + |
| 218 | +public MyPublicFunction(playerid, const string[]) |
| 219 | +{ |
| 220 | +} |
| 221 | +``` |
| 222 | +
|
| 223 | +Sem o `forward`, o compilador precisa “reprocessar” quando encontra uma função que retorna, por exemplo, `Float:` antes da definição. Outra alternativa é declarar a função antes do uso, mas o `forward` evita reorganizar o arquivo. |
| 224 | +
|
| 225 | +## `native` |
| 226 | +
|
| 227 | +Nativas são funções implementadas fora do script (no servidor ou em plugins). Você só pode declará-las se já existir uma implementação; porém, pode criar “falsas” nativas para listar funções no painel do Pawno. |
| 228 | +
|
| 229 | +```c |
| 230 | +native printf(const format[], {Float,_}:...); |
| 231 | +``` |
| 232 | + |
| 233 | +Para exibir uma função personalizada na lista sem declará-la de fato: |
| 234 | + |
| 235 | +```c |
| 236 | +/* |
| 237 | +native MyFunction(playerid); |
| 238 | +*/ |
| 239 | +``` |
| 240 | + |
| 241 | +O Pawno não interpreta comentários e adiciona o símbolo na lista, enquanto o compilador ignora a linha. |
| 242 | + |
| 243 | +Também é possível renomear ou encapsular nativas: |
| 244 | + |
| 245 | +```c |
| 246 | +native my_print(const string[]) = print; |
| 247 | + |
| 248 | +print(const string[]) |
| 249 | +{ |
| 250 | + my_print("Someone called print()"); |
| 251 | + my_print(string); |
| 252 | +} |
| 253 | +``` |
| 254 | +
|
| 255 | +Agora toda chamada a `print` passa pelo wrapper. |
| 256 | +
|
| 257 | +## `new` |
| 258 | +
|
| 259 | +Declara variáveis; por padrão começam em 0. |
| 260 | +
|
| 261 | +```c |
| 262 | +new |
| 263 | + myVar = 5; |
| 264 | +``` |
| 265 | + |
| 266 | +O escopo depende das chaves onde é declarado. Variáveis globais (`new` fora de funções) podem ser usadas em qualquer ponto após a declaração. Se o arquivo incluir outros, eles também terão acesso, a menos que você use `static`. |
| 267 | + |
| 268 | +## `operator` |
| 269 | + |
| 270 | +Permite sobrecarregar operadores para tags personalizadas. Exemplo para armazenar números em big endian: |
| 271 | + |
| 272 | +```c |
| 273 | +stock BigEndian:operator=(value) |
| 274 | +{ |
| 275 | + return BigEndian:(((value >>> 24) & 0x000000FF) | |
| 276 | + ((value >>> 8) & 0x0000FF00) | |
| 277 | + ((value << 8) & 0x00FF0000) | |
| 278 | + ((value << 24) & 0xFF000000)); |
| 279 | +} |
| 280 | +``` |
| 281 | + |
| 282 | +Operadores suportados: `+`, `-`, `*`, `/`, `%`, `++`, `--`, `==`, `!=`, `<`, `>`, `<=`, `>=`, `!` e `=`. |
| 283 | + |
| 284 | +Eles podem executar qualquer lógica, inclusive ignorar o comportamento padrão. |
| 285 | + |
| 286 | +## `public` |
| 287 | + |
| 288 | +Transforma funções (ou variáveis) em símbolos acessíveis pelo servidor. Todas as callbacks do SA:MP são `public`. O nome textual da função é armazenado no AMX, o que permite chamá-la por `CallLocalFunction`, `SetTimerEx`, etc. Para isso é obrigatório declarar um `forward`. |
| 289 | + |
| 290 | +```c |
| 291 | +forward MyPublicFunc(); |
| 292 | + |
| 293 | +main() |
| 294 | +{ |
| 295 | + CallLocalFunction("MyPublicFunc", ""); |
| 296 | +} |
| 297 | + |
| 298 | +public MyPublicFunc() |
| 299 | +{ |
| 300 | + printf("Hello"); |
| 301 | +} |
| 302 | +``` |
| 303 | + |
| 304 | +Funções públicas também podem ser chamadas normalmente dentro do script (`MyPublicFunc();`), o que é bem mais rápido do que invoques por string. |
| 305 | + |
| 306 | +## `static` |
| 307 | + |
| 308 | +`static` aplicado globalmente cria variáveis visíveis apenas no arquivo (ou `#section`) onde foram declaradas. Diferente de `new`, a visibilidade não se estende a arquivos incluídos. |
| 309 | + |
| 310 | +Localmente, `static` mantém o valor entre chamadas: |
| 311 | + |
| 312 | +```c |
| 313 | +MyFunc() |
| 314 | +{ |
| 315 | + static |
| 316 | + counter = 0; |
| 317 | + printf("%d", counter); |
| 318 | + counter++; |
| 319 | +} |
| 320 | +``` |
| 321 | + |
| 322 | +A primeira chamada imprime 0, a segunda 1 e assim por diante. Com `new`, o valor seria reiniciado em cada execução. Também é possível declarar funções `static` para “privatizá-las”. |
| 323 | + |
| 324 | +## `stock` |
| 325 | + |
| 326 | +`stock` serve para declarar funções ou variáveis opcionais, sem gerar avisos de “unused”. Se o símbolo for usado, o compilador o inclui; caso contrário, ele é descartado. |
| 327 | + |
| 328 | +```c |
| 329 | +stock Func1() |
| 330 | +{ |
| 331 | + printf("Hello"); |
| 332 | +} |
| 333 | + |
| 334 | +stock Func2() |
| 335 | +{ |
| 336 | + printf("Hi"); |
| 337 | +} |
| 338 | +``` |
| 339 | + |
| 340 | +Útil para bibliotecas, onde você não sabe quais funções o usuário vai chamar. Diferentemente de `#pragma unused`, o código nem chega a ser emitido se não houver uso. |
0 commit comments