[Tutorial] Alocaзгo.
#1

Alocaзгo.
Por rjjj ou Ken




Alocaзгo de dados й a reservaзгo de parte da memуria do computador para um determinado fim .



O termo "alocaзгo" significa destinaзгo. Isso quer dizer que quando alguma coisa й alocada, esta й destinada a participar de um acontecimento.



Nas linguagens de programaзгo, essa palavra estб relacionada а criaзгo de variбveis pelo programador :



pawn Код:
new x;  //Esse cуdigo aloca a variбvel "x" na memуria. Isso significa que ele destina a mesma a ser colocada lб.




1 - Teoria.




Hб dois tipos de alocaзгo: a estбtica e a dinвmica .



Na alocaзгo estбtica, o escritor do cуdigo dб, de certa forma, um tamanho fixo a uma variбvel.



Isso й mais perceptнvel em se tratando de variбveis arrays, por estas serem sempre um tipo de variбvel cujo tamanho й definido pelo programador. Um exemplo na linguagem C, com a qual Pawn foi feito:


Код:
int y[128];  //Essa linha aloca a variбvel "y" de tamanho 128 na memуria.


Jб na alocaзгo dinвmica, o tamanho da variбvel pode resultar de fatores presentes durante a execuзгo do programa. Em C, por exemplo :


Код:
int *y = (int *) calloc(128, sizeof(int));


O cуdigo acima faria basicamente a mesma coisa que o anterior, mas nele, se quisйssemos, poderнamos regular o tamanho da variбvel a ser criada de acordo com algo que nгo й conhecido pelo programador.



Como assim ?



Bem, digamos que vocк declare uma variбvel array de tamanho fixo igual a 10 para que a mesma armazene o texto de entrada de um indivнduo.



Se o que o indivнduo digitasse tivesse 20 caracteres, a variбvel nгo conseguiria armazenar tudo e "estouraria", ou seja, sofreria um overflow.



Por outro lado, se tivesse 2 caracteres, memуria seria ocupada sem necessidade.



Com alocaзгo dinвmica, o tamanho da variбvel poderia ser ajustado dependendo do que fosse colocado pelo indivнduo. Sу precisaria tomar cuidado com a capacidade dele definir a quantidade de memуria do computador a ser ocupada .





Certas versхes da linguagem Pawn aceitam os dois tipos de alocaзгo.



Entretanto, o SA-MP Pawn sу disponibiliza a alocaзгo estбtica. Por isso o seguinte cуdigo geraria problemas na compilaзгo :


pawn Код:
new y[GetMaxPlayers()];  //Tentaria criar a variбvel "y" com tamanho igual ao total de slots do servidor.


Mais detalhadamente, isso ocorre pelo fato de o compilador ter que registrar o tamanho absoluto de todas as variбveis no arquivo .amx.



Apesar dos problemas que citei antes, graзas а alocaзгo estбtica, hб um fбcil controle por parte do programador sobre a existкncia de variбveis na memуria.





2 - Estбtica.




A alocaзгo estбtica й efetuada junto do mйtodo comum de declaraзгo de variбveis :



pawn Код:
#include <a_samp>


new o[20];  //Declara a variбvel array "o" de tamanho 20 e a aloca estaticamente na memуria.


main()
{
    new i[50];  //Declara a variбvel array "i" de tamanho 50 e a aloca estaticamente na memуria.
}


A regra й: o que fica dentro dos colchetes das variбveis arrays no momento da declaraзгo das mesmas tem que ser um nъmero natural constante nгo-nulo.



Sendo assim, pode-se fazer isto :



pawn Код:
#include <a_samp>


new o[2 * 10];  //Declara a variбvel array "o" de tamanho 20 e a aloca estaticamente na memуria.


main()
{
    new i[30 + 20];  //Declara a variбvel array "i" de tamanho 50 e a aloca estaticamente na memуria.
}


Pois 2 * 10 sempre seria igual a 20 e 30 + 20 igual a 50 .



Porйm, vocк jб deve ter visto cуdigos como estes serem compilados com sucesso:


pawn Код:
#define Abc 40
new Array[Abc];

pawn Код:
enum Abc
{
    a,
    b,
    c
};
new Array[Abc];


Quando isso ocorre, significa que de alguma forma o compilador conseguiu encontrar o tamanho da variбvel.



No primeiro cуdigo, devido ao sнmbolo Abc ter sido definido pela diretiva #define, ele й, em todos os lugares do GM/FS, substituнdo pelo nъmero 40 antes da compilaзгo propriamente dita .



Jб o caso do segundo cуdigo pode ser explicado pelo fato de alguns elementos da linguagem Pawn, apesar de nгo parecerem, resultarem em valores que podem ser detectados antes da execuзгo do arquivo .amx.



Dentre eles, destacam-se:



Код:
- enum.

- const.

- sizeof.

- defined.


Entгo, o cуdigo abaixo seria vбlido:



pawn Код:
new a[31];  //Declara a variбvel "a" de tamanho 31.
new e[sizeof(a)];  //Declara a variбvel "e" de tamanho 31.



Vale ressaltar que isto nгo funcionaria porque como strlen й lido no processamento, nгo haveria maneira de detectar o nъmero retornado por ele no prй-processamento ou na compilaзгo :



pawn Код:
new Var[strlen("rjjj")];


Se tentasse ser compilada como global, a variбvel acima geraria um arquivo .amx de 0 bytes.



Caso local, geraria o erro "must be a constant expression", que pode ser traduzido como "tem que ser uma expressгo constante".



Obs: O sizeof de uma variбvel scalar (nгo-array) й sempre igual a 1.





3 - Dinвmica.




O SA-MP Pawn realmente nгo aceita alocaзгo dinвmica.



Contudo, aceita plugins, que permitem alocaзгo dinвmica .



Por isso, nesta seзгo do tutorial, utilizaremos o plugin CSTL - Data container(s) (Currently vector).




* Criaзгo de arrays



Primeiramente vamos aprender a criar uma variбvel array dinamicamente. Isso й feito pela funзгo abaixo:


pawn Код:
vector_resize(/* ID da variбvel array */,  /* Tamanho da variбvel array */);

O plugin identifica as variбveis arrays criadas por ele por IDs, nгo por nomes. Nгo ultrapassando o limite de constituiзгo binбria, qualquer nъmero inteiro pode ser um ID .



Exemplo:


pawn Код:
vector_resize(1, 8);  //Cria a variбvel array de ID 1 e define o tamanho dela como igual a 8. Como se fosse "new x[8];".


No cуdigo acima, se quisйssemos, poderнamos ter passado strlen("abc") ao segundo parвmetro da funзгo vector_resize em vez de 8, assim obtendo o hipotйtico resultado de new x[strlen("abc")];.




* Atribuiзгo de valores



Para atribuir um valor a uma parte de uma array dinвmica, hб as funзхes vector_set (inteiros), vector_set_float (racionais/floats) e vector_set_arr (arrays e strings):


pawn Код:
vector_set(/* ID da variбvel array */, /* Нndice da parte da array para a qual atribuiremos um valor */, /* Nъmero do tipo inteiro */);
pawn Код:
vector_set_float(/* ID da variбvel array */, /* Нndice da parte da array para a qual atribuiremos um valor */, /* Nъmero do tipo ponto-flutuante */);
pawn Код:
vector_set_arr(/* ID da variбvel array */, /* Нndice da parte da array para a qual atribuiremos um valor */, /* String ou nome de uma array*/);


Exemplo:


pawn Код:
vector_resize(1, 5);  //Cria a variбvel array de ID 1 com tamanho 5. Como se fosse "new x[5];".
vector_resize(2, 10);  //Cria a variбvel array de ID 2 com tamanho 10. Como se fosse "new y[10];".
vector_resize(3, 20);  //Cria a variбvel array de ID 3 com tamanho 20. Como se fosse "new z[20];".
vector_set(1, 3, 100);  //Atribui б parte de нndice 3 da array de ID 1 o valor 100. Como se fosse "x[3] = 100;".
vector_set_float(2, 7, 3.14);  //Atribui б parte de нndice 7 da array de ID 2 o valor 3.14. Como se fosse "y[7] = 3.14;".
vector_set_arr(3, 18, "Texto");  //Atribui б parte de нndice 18 da array de ID 3 o valor "Texto". Como se fosse "z[18] = "Texto"".


Com essa ъltima funзгo, tambйm й possнvel alocar dinamicamente variбveis arrays multi-dimensionais :


pawn Код:
new Var[5] = {10, 9, 8, ...};  //Aloca a variбvel array "Var" estaticamente com tamanho igual a 5.
vector_resize(4, 20);  //Aloca a variбvel array de ID 4 dinamicamente, com tamanho igual a 20.
vector_set_arr(4, 0, Var);  //Armazena a array "Var" na parte de нndice 0 da array de ID 4. Isso resulta em algo similar a "new x[20][5];", isto й, array dentro de array.



* Obtenзгo de valores



Obtйm-se o valor de determinada parte de uma array dinвmica atravйs das funзхes vector_get (inteiros), vector_get_float (racionais/floats) e vector_get_arr (arrays e strings):


pawn Код:
vector_get(/* ID da variбvel array */, /* Нndice da parte da array da qual obteremos o valor */);
pawn Код:
vector_get_float(/* ID da variбvel array */, /* Нndice da parte da array da qual obteremos o valor */);
pawn Код:
vector_get_arr(/* ID da variбvel array */, /* Нndice da parte da array da qual obteremos o valor */, /* Array para armazenar o valor da parte da array dinвmica */, /* Tamanho da array que conterб o valor */ );


A tag do valor de retorno da primeira e da segunda funзгo serб de acordo com o que estб na parte da array dinвmica.



Jб na terceira, o valor armazenado na parte da array dinвmica й passado a uma array comum de Pawn de maneira similar ao que ocorre em GetPlayerName.



Exemplo:


pawn Код:
new Inteiro;
new Float:Flutuante;
new Array[20];
Inteiro = vector_get(1, 10);  //Armazena na variбvel "Inteiro" o valor na parte de нndice 10 da array dinвmica de ID 1. Como se fosse "Inteiro = x[10];".
Flutuante = vector_get_float(2, 50);  //Armazena na variбvel "Flutuante" o valor na parte de нndice 50 da array dinвmica de ID 2. Como se fosse "Flutuante = y[50];".
vector_get_arr(3, 25, Array, sizeof(Array));  //Armazena na variбvel "Array" o valor na parte de нndice 25 da array dinвmica de ID 3. Como se fosse "Array = z[25];", sendo "z" multi-dimensional.



* Remoзгo de arrays



A seguinte funзгo remove da memуria um dado especнfico de uma variбvel array :


pawn Код:
vector_remove(/* ID da variбvel array */, /* Нndice da parte da array que serб removida */);


Exemplo:


pawn Код:
vector_resize(1, 3);  //Cria a array de ID 1 com tamanho 3.
vector_set(1, 0, 1000);  //Armazena na parte 0 da array de ID 1 o nъmero 1000.
vector_set(1, 1, 2000);  //Armazena na parte 1 da array de ID 1 o nъmero 2000.
vector_set(1, 2, 3000);  //Armazena na parte 2 da array de ID 1 o nъmero 3000.
vector_remove(1, 1);  //Remove da memуria a parte 1 da array.
printf("Valor da parte 0: %d", vector_get(1, 0));  //Mostraria o nъmero 1000.
printf("Valor da parte 1: %d", vector_get(1, 1));  //Mostraria o nъmero 3000, pois o 2000 foi excluнdo junto da antiga parte 1 da array.
printf("Valor da parte 2: %d", vector_get(1, 2));  //Mostraria o nъmero -1, pois o que era a parte 2 da array virou a nova parte 1, entгo nгo existe mais.


Percebe-se que a array й reorganizada se uma parte dela й excluнda.



Arrays dinвmicas tambйm podem ser destruнdas, com a seguinte funзгo:


pawn Код:
vector_clear(/* ID da array a ser destruнda */);

Exemplo:


pawn Код:
vector_clear(2);  //Destrуi, isto й, remove da memуria a array de ID 2.



* Modificaзгo de tamanho de arrays



Modifica-se o tamanho de uma array atravйs da funзгo vector_resize, a mesma que й usada para criar uma array:


pawn Код:
vector_resize(/* ID da variбvel array */, /* Novo tamanho que a array terб */);


Exemplo:


pawn Код:
vector_resize(1, 40);  //Muda o tamanho da array de ID 1 para 40.


Se o tamanho da array do exemplo antes fosse 60 por exemplo, ocorreria perda de dados pois as partes de нndice 40 a 59 seriam destruнdas .




* Capturar tamanho de array



Para capturar o tamanho de uma array, hб a funзгo vector_size:


pawn Код:
vector_size(/* ID da variбvel array cujo tamanho serб retornado */);


Exemplo:


pawn Код:
printf("Tamanho da array de ID 3: %d", vector_size(3));


As arrays dinвmicas podem ser acessadas de qualquer escopo.



E essas sгo as principais funзхes para alocaзгo dinвmica no SA-MP Pawn .





4 - Outros.




Para que serviria a alocaзгo dinвmica ?



O criador de um sistema de salvamento de dados em arquivos por exemplo nгo precisaria dar um tamanho mбximo para suas variбveis, aзгo que muitas vezes й responsбvel pela ocupaзгo desnecessбria de memуria .



Bastaria utilizar alocaзгo dinвmica, assim poupando recursos.



Alйm disso, se as variбveis fossem estбticas seria possнvel reduzir bastante o tamanho do arquivo .amx, apesar de que isso traria, por um certo perнodo de tempo, uma maior carga de processamento.



PVars e properties tambйm sгo dados que sofrem alocaзгo para existirem. Isso й feito dinamicamente, mesmo eles nгo sendo como as tradicionais variбveis arrays.




Espero ter ajudado .
Reply
#2

Cara, aprendi a codar com seus tutoriais e sempre entendi tudo o que foi dito por eles.

Meus parabйns, mais um tutorial excelente que irб ajudar muitas pessoas
Reply
#3

Excelente tutorial. Mais uma vez, meus parabйns.
Reply
#4

Nice one! Congratulations, once again with a nice tutorial.
Reply
#5

Caralho, aja paciкncia spider pra fazer um tutorial desse o.O

Muito bom como sempre rjj.
Reply
#6

Muito bom Rjjj, Parabйns!
Reply
#7

Muito bom o tutorial Ken, bem explicado e tudo.

Sу pra dar uma incrementada no tutorial, pVars e Propertys tambйm sгo tipos de alocaзхes, mas estб se destacam por serem maleбveis (de fбcil manipulaзгo), acessadas por strings e serem totalmente dinвmicas Explica aн.
Reply
#8

Muito Obrigado a Todos !



Quote:
Originally Posted by [FeK]DraKiNs
Посмотреть сообщение
Muito bom o tutorial Ken, bem explicado e tudo.

Sу pra dar uma incrementada no tutorial, pVars e Propertys tambйm sгo tipos de alocaзхes, mas estб se destacam por serem maleбveis (de fбcil manipulaзгo), acessadas por strings e serem totalmente dinвmicas Explica aн.
Coloquei algumas informaзхes sobre isso no tutorial.



Espero ter ajudado .
Reply
#9

Quote:
Originally Posted by rjjj
Посмотреть сообщение
Muito Obrigado a Todos !






Coloquei algumas informaзхes sobre isso no tutorial.



Espero ter ajudado .
Quote:

PVars e properties tambйm sгo dados que sofrem alocaзгo para existirem.

Explica mais, meu querido. Tб muito pouco
Reply
#10

Excelente tuto Parabens
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)