@68tjs
bricofoy a raison - si la signature de la fonction demande un int le compilateur et l'optimiser ne vont pas s'amuser unilatéralement à retourner un seul octet.
Si vous regardez le code source vous voyez que (en gros) ils retournent HIGH ou LOW
if (*portInputRegister(port) & bit) return HIGH;
return LOW;
or HIGH et LOW sont définis ici non pas comme des constantes typées, mais par un #define
#define HIGH 0x1
#define LOW 0x0
et donc seront soumis aux lois de l'usage par défaut de constantes numériques lors de leur remplacement dans le code. en C ou C++ ça veut dire qu'ils seront considérés comme des int (et sur un ATMEGA ce sera donc 2 octets en entier signé, sur un ESP ce sera 4 octets)
68tjs:
Je fais de l'abstraction :
La fonction digitalRead c'est un voltmètre tout ou rien.
Le voltmètre à l'entrée du micro mesure 5V -> je dis présence de signal = vraie
Le voltmètre à l'entrée du micro ne mesure rien (ou 0V c'est la même chose) -> je dis présence de signal = faux
C'est bien une opération logique que je fais.
Oui dans votre tête vous effectuez cette abstraction, c'est comme cela que vous vous représentez la fonction... Mais ce n'est pas ce que fait le code. Pour faire ce que vous dites il aurait fallu définir la fonction comme cela:
bool presenceTension(uint8_t pin)
{
uint8_t timer = digitalPinToTimer(pin);
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
if (port == NOT_A_PIN) return false;
// If the pin that support PWM output, we need to turn it off
// before getting a digital reading.
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
return ((*portInputRegister(port) & bit) != 0);
}
et dans ce cas le compilateur n'a pas d'opération magique à faire derrière votre dos, vous retournez bien une valeur de vérité.
En pratique la fonction digitalRead retourne un entier signé qui vaut 1 ou 0 et ensuite - et seulement ensuite - suivant ce que vous faites avec cette valeur, le compilateur va générer du code en plus pour convertir cet entier en valeur de vérité:
// imaginons que la pin 2 soit HIGH
int x = (digitalRead(2) + 1) * 5; // x vaudra 10
bool x = (digitalRead(2) + 1) * 5; // x vaudra true
Dans le premier cas on traite le résultat de digitalRead comme un entier, et donc x vaudra 10, le compilateur ne rajoute aucun code. Dans le second cas le compilateur évalue la partie droite, trouve 10 et comme il voit qu'ensuite il faut affecter cela dans un booléen, le compilateur génère du code (selon la norme) qui va comparer le résultat obtenu à 0 et si c'est zéro mettre false
dans x, si ce n'est pas zéro mettre true
dans x.
@bricofoy
bricofoy:
cela évolue avec les version du compilateur, non, la manière de gérer les booléens ? J'ai souvenir de pouvoir faire booleen+=1 pour en changer l'état il n'y a pas si longtemps (en incrémentant le premier bit de l'octet, on le faisait passer de 0 à 1 et inversement, et c'est même en cours d'informatique que j'avais appris à faire ça, en école d'ingénieur en 2001...), ce qui ne fonctionne pas avec la version actuelle comme vous venez de l'expliquer puisque c'est alors la valeur totale qui est prise en compte et non plus le seul premier bit.
Tout à fait, depuis C++11 le standard interdit de décrémenter un booléen (résultat indéterminé, dépendant du compilo) et après C++17 le standard ne supporte plus l'incrémentation d'un booléen. (donc b++ par exemple qu'on pouvait utiliser pour alterner le bit de poids faible).
Bref - tout ce que je dis c'est qu'à mon avis il vaut mieux rester maître des types que l'on utilise. Le typage fort évite bien des désagrément et des sessions de debug pénibles. Comprendre ce que fait le compilateur dans votre dos et suivre les évolutions de la norme c'est pas toujours simple. Donc ma recommandation, si vous utilisez un booléen, mettez dedans une valeur de vérité (le résultat d'un test). Comme cela vous maitrisez le code. Si vous devez faire des opérations sur un type booléen, les seules autorisées sont celles de la logique booléenne (&&, || etc)
MAIS je suis bien d'accord que la norme définit explicitement la promotion d'une valeur intégrale vers une valeur de vérité, en disant que 0 devient faux et tout le reste devient vrai. Donc si vous êtes à l'aise avec ce que génère le compilo pour vous, pas de soucis non plus à utiliser cela - c'est la norme donc tout à fait correct.
Pour ma part je réserve cela à l'écriture des expressions dans un if ou un while par exemple quand j'ai un peu la flemme de rajouter le != 0
dans la condition et que je sais que le compilateur va le faire pour moi