A IDE padrão do Arduino, utiliza C/C++, e o que eu quero mostrar aqui são algumas pegadinhas em que as vezes programadores menos experientes podem cair.
C/C++ é uma linguagem Fortemente Tipada. Isso significa que sempre que formos declarar uma variável, precisamos definir a que tipo de dados ela pertence.
Os principais tipos de variáveis são:
void
boolean
char
unsigned char
byte
int
unsigned int
word
long
unsigned long
short
float
double
string - char array
String - object
array
Minha intenção não é apresentar e explicar os tipos de dados utilizados para programar o Arduino, mas mostrar alguns detalhes que devemos prestar atenção na hora de programar.
Se olharmos os tipos acimas, veremos que alguns deles, como int, char e long, possuem o tipo unsigned, por exemplo, tem int, e tem unsigned int.
Mas qual a diferença entre esses dois tipos? Para exemplificar vamos pegar os tipos int e unsigned int. Tanto um como outro irá reservar 16 bits de memória para cada variável declarada. A diferença é que int armazena números que vão de -32.768 a 32.767, ou seja, aceita números negativos. Enquanto que unsigned int, armazena números de 0 a 65.535.
Agora vamos imaginar o seguinte, iremos declarar duas variáveis, uma variável i do tipo int, e uma variável u do tipo unsigned int e inicializamos cada uma com o valor 0.
Se agora fizermos um if verificando se i é igual a u, obviamente o if será verdadeiro, pois ambas possuem valor 0.
Agora supomos que o valor das duas variáveis sejam decrementadas em 1 (i-- e u--). Vamos analisar então o que acontece com cada uma das variáveis.
Se i era igual a 0, agora ela será igual a -1. Já no caso de u, é diferente, pois u não pode armazenar valores negativos. Nesse caso, u-- var resultar no seguinte valor: 65.535. Isso mesmo. O valor assumido é o último valor dos possíveis valores para o tipo unsigned int. Isso sempre acontece quando extrapolamos os valores aceitos por esses tipos de dados, seja no início ou no fim.
Pois bem, considerando então que i é igual a -1 e u igual a 65.535, o que aconteceria se novamente verificássemos se i é igual a u. Apesar de não ser tão óbvio agora, a comparação continuaria resultado verdadeiro. Sim. -1 seria igual a 65.535.
O que acontece aqui é o seguinte: Quando uma comparação entre dois tipos é feita, é preciso que o compilador converta os tipos de dados para um mesmo tipo, e nessa conversão, os dados resultantes da conversão dos tipos de dados vão ser os mesmos, ou seja iguais. O que, dependendo da lógica que está sendo programada, pode levar a erros. E o programador menos experiente pode ficar doidinho tentando entender o que está acontecendo e não conseguir achar o problema.
Sketch com o exemplo acima
int i = 0; /* -32.768 .. 32.767 */ unsigned int u = 0; /* 0 .. 65.535 */ void setup() { Serial.begin(9600); } void loop() { Serial.print("i = "); Serial.print(i); Serial.println(""); Serial.print("u = "); Serial.print(u); Serial.println(""); if (i == u) { Serial.println("iguais"); } else { Serial.println("diferentes"); } i--; u--; delay(5000); Serial.println(""); Serial.println(""); }
Vamos imaginar agora um exemplo parecido, mas ao invés de decrementarmos as duas variaveis, vamos decrementar apenas i e iremos verificar se i é maior, menor ou igual a u.
int i = 0; /* -32.768 .. 32.767 */ unsigned int u = 0; /* 0 .. 65.535 */ void setup() { Serial.begin(9600); } void loop() { Serial.print("i = "); Serial.print(i); Serial.println(""); Serial.print("u = "); Serial.print(u); Serial.println(""); if (i == u) { Serial.println("iguais"); } else { if (i > u) { Serial.println("i maior que u"); } else { Serial.println("u maior que i"); } } i--; //apenas i é decrementado delay(5000); Serial.println(""); Serial.println(""); }
Veja que mesmo i sendo negativo, o programa entende que i é maior que zero. Isso acontece pelo mesmo motivo mostrado anteriormente. O compilador precisa converteri, que é int, em unsigned int. pois só pode comparar variáveis do mesmo tipo, e nessa conversão de um tipo para outro, o valor que era -1, passa a ser 65.535, ou seja, após a conversão, i de fato passa a ser maior que u.
Conclusão
Sempre que for declarar o tipo de dado, pense exatamente o que aquele dado vai representar, se de fato pode ou não haver valores negativos. E se haver, pense nos problemas que podem ocorrer. E procure não misturar os tipos de dados na hora de fazer comparações ou outras operações entre eles. E o principal: Sempre teste seu código com todas as possibilidades de valores.
Nenhum comentário:
Postar um comentário