Bonjour,
J'utilise l'ide 1.8.16 avec une carte Uno.
Je me suis intéressé à la fonction abs qui est définie dans Arduino.h de la façon suivante:
#define abs(x) ((x)>0?(x):-(x))
Je note qu'il n'y a pas de type défini.
Avec le programme:
void setup()
{
Serial.begin(115200);
Serial.print("abs(10) = "); Serial.println(abs(10));
Serial.print("sizeof(abs(10)) = "); Serial.println(sizeof(abs(10)));
Serial.println();
Serial.print("abs(-10) = "); Serial.println(abs(-10));
Serial.print("sizeof(abs(-10)) = "); Serial.println(sizeof(abs(-10)));
Serial.println();
Serial.print("abs(32767) = "); Serial.println(abs(32767));
Serial.print("sizeof(abs(32767)) = "); Serial.println(sizeof(abs(32767)));
Serial.println();
Serial.print("abs(-32768) = "); Serial.println(abs(-32768));
Serial.print("sizeof(abs(-32768)) = "); Serial.println(sizeof(abs(-32768)));
Serial.println();
}
void loop()
{
}
J'obtiens bien ce que j'attends:
abs(10) = 10
sizeof(abs(10)) = 2abs(-10) = 10
sizeof(abs(-10)) = 2abs(32767) = 32767
sizeof(abs(32767)) = 2abs(-32768) = 32768
sizeof(abs(-32768)) = 4
Par défaut tout est en int, tant que c'est dans la limite [-32768, 32787] et si -32768 est un int son opposé ne tenant pas passe dans un long, et j'ai bien 4 octets. Mais le problème se pose quand je mets toutes ses valeurs dans un int.
Je teste le programme suivant:
void fonction(int parametre) // Permet l'analyse du paramètre
{
int parametreAbs = abs(parametre); // Un bel int sur 2 octets
unsigned long depart = millis(); // Pour avoir une idée du nombre de boucles faites
Serial.print("sizeof(parametreAbs) = "); Serial.println(sizeof(parametreAbs)); // Normalement 2
Serial.print("parametreAbs = "); Serial.println(parametreAbs); // normalement dans [-32768, 32767]
while (parametreAbs > 0)
{
parametreAbs--;
delay(1); // Permet de compter le nombre approximatif de boucles, chacune durant environ 1ms
}
Serial.print(millis() - depart); Serial.println("ms"); // Et affichange du temps
Serial.println();
}
void setup()
{
Serial.begin(115200);
}
void loop()
{
fonction(100); // Devrait faire 100 boucles
fonction(-32768); // Ne devrait rien faire du tout si parametreAbs = -32768
}
Mais j'obtiens un résultat curieux:
sizeof(parametreAbs) = 2
parametreAbs = 100
100mssizeof(parametreAbs) = 2
parametreAbs = 4294934528
32898ms
Pour fonction(100);
tout est normal. Je passe 100, la valeur absolue est 100, cela tient dans un int, la taille indiquée est 2, et la boucle dure 100ms (des fois 101ms), il y a donc bien les 100 boucles.
Pour fonction(-32768);
parametre vaut -32768 , c'est un int 16 bits, la valeur absolue ne tient pas dans le int, il y a dépassement de la capacité mais c'est normal, je m'y attends. Et quand je range la valeur -32768 dans parametreAbs qui est un int, le programme me dit que cela occupe bien 2 octets, mais que la valeur est 4294934528 qui ne peut pas rentrer.
Que contient réellement parametreAbs?
Des fois 4294934528 comme pour l'affichage
Des fois un nombre positif sinon, je ne ferais pas le while
Des fois +32768 ou à peu près sinon le nombre de boucles ne serait pas bon.
Je me suis dit que pour être sûr je vais transtyper abs(parametre) en int en mettant:
int parametreAbs = (int)abs(parametre); // Un bel int sur 2 octets
Mais cela donne toujours le même résultat.
Pour que cela soit plus bizarre, si on supprime dans loop la ligne
fonction(100); // Devrait faire 100 boucles
On obtiens ce que j'attendais, une suite de:
sizeof(parametreAbs) = 2
parametreAbs = -32768
4ms
J'aurais le résultat inverse, je me dirais que si la fonction n'est appelée qu'une fois, le compilateur pourrait comprendre que je veux faire 32768 boucles et coder cela en dur sans utiliser les variables. Mais c'est l'inverse!
On dit souvent que pour comprendre on peut rajouter un print de la variable. En rajoutant l'affichage de la valeur absolue:
void fonction(int parametre) // Permet l'analyse du paramètre
{
int parametreAbs = (int)abs(parametre); // Un bel int sur 2 octets
unsigned long depart = millis(); // Pour avoir une idée du nombre de boucles faites
Serial.print("sizeof(parametreAbs) = "); Serial.println(sizeof(parametreAbs)); // Normalement 2
Serial.print("parametreAbs = "); Serial.println(parametreAbs); // normalement dans [-32768, 32767]
while (parametreAbs > 0)
{
Serial.print("dans while -> parametreAbs = "); Serial.println(parametreAbs); // normalement dans [-32768, 32767]
parametreAbs--;
delay(1); // Permet de compter le nombre approximatif de boucles, chacune durant environ 1ms
}
Serial.print(millis() - depart); Serial.println("ms"); // Et affichange du temps
Serial.println();
}
void setup()
{
Serial.begin(115200);
}
void loop()
{
fonction(100); // Devrait faire 100 boucles
fonction(-32768); // Ne devrait rien faire du tout si parametreAbs = -32768
}
J'obtiens:
sizeof(parametreAbs) = 2
parametreAbs = -32768
dans while -> parametreAbs = -32768
dans while -> parametreAbs = 32767
dans while -> parametreAbs = 32766
dans while -> parametreAbs = 32765
dans while -> parametreAbs = 32764
dans while -> parametreAbs = 32763
dans while -> parametreAbs = 32762
dans while -> parametreAbs = 32761
dans while -> parametreAbs = 32760
dans while -> parametreAbs = 32759
Cela change la valeur de parametreAbs qui passe de 4294934528 à -32768 comme je m'y attendais mais je rentre dans la boucle avec une valeur négative.
Je fais combien d'erreurs?