Pourquoi mon test de signe indique-t-il toujours un résultat «négatif»?

Le programme suivant doit indiquer si la sum des éléments du tableau est positive ou négative:

#include  #define ARR_SIZE 5 int main() { int array[ARR_SIZE] = {1,-2,3,4,-5}; unsigned sum; int i; for(i=0, sum=0; i -1) printf("non negative\n"); else printf("negative\n"); return 0; } 

Le programme ne fait pas ce qu’il est censé faire; il affiche ‘négatif’, peu importe les valeurs de tableau qu’il reçoit.

Par exemple, la sum du tableau écrit dans le programme ci-dessus est égale à 1 et je m’attendais donc à la sortie suivante:

 sum 1 sum -1 sum 2 sum 6 sum 1 1 non negative 

Alors que la sortie est:

 sum 1 sum -1 sum 2 sum 6 sum 1 1 negative 

Pourquoi ai-je cette sortie?

Dans l’expression sum > -1 , les conversions arithmétiques habituelles (“équilibrage”) s’appliquent. Puisqu’un opérande est unsigned int et l’autre int , l’opérande -1 qui est int est converti implicitement en unsigned int . La comparaison est effectuée sur le type unsigned int .

De plus, les variables non signées ne peuvent jamais contenir de valeur négative. Par conséquent, l’expression n’a aucun sens, même sans conversion implicite.

Conversion de type implicite: lorsque vous définissez une variable comme non signée et la comparez à un nombre négatif, ce nombre négatif est converti de manière implicite. Comme nous le soaps, les nombres négatifs sont stockés dans le complément à deux, donc -1 devient en fait un très grand nombre positif. Maintenant, quel que soit le grand nombre que vous fournissez, il sera toujours inférieur à ce grand nombre, c’est pourquoi vous obtenez une réponse négative tout le temps.

Solution possible: utilisez l’opérateur ternaire pour gérer les nombres + et -. Merci

la sortie en raison de votre déclaration de variable sum , vous l’avez déclarée en tant que unsigned sum suffit de changer la unsigned sum signed sum ou en int sum

Avec un ensemble raisonnable d’avertissements activé, un bon compilateur mettra en évidence le problème:

 gcc -std=c11 -fPIC -g -Wall -Wextra -Wwrite-ssortingngs -Wno-parentheses -Wpedantic -Warray-bounds 42362568.c -o 42362568 42362568.c: In function 'main': 42362568.c:19:10: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] if(sum>-1) printf("non negative\n"); ^ 

C’est toujours un bon conseil d’activer autant d’alertes que possible. pour des raisons historiques, la plupart des compilateurs donnent très peu d’avertissements à moins que vous ne vous souveniez de les demander.

Notez que si vous modifiez la comparaison en if (sum >= 0) , vous obtiendrez un message différent (et peut-être plus utile), car le littéral 0 peut être traité comme 0u :

 42362568.c:19:10: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits] if(sum>=0) printf("non negative\n"); ^~ 

Lorsque nous essayons de comparer deux signes de variables différents (même type de données), le compilateur traitera implicitement (en interne) les deux variables en tant que type signé (type non signé).

Écoutez if(sum > -1) est votre code. Vous essayez de comparer une unsigned sum , signed constant afin que le compilateur convertisse en interne -1 as unsigned . Si nous considérons la taille entière comme 2 octets, sum = 1(as your code) mais le -1 will be converted to unsigned value 65535 (do 2's compliment for -1) votre code sera simplifié if(sum > 65535) la condition est donc FALSE c’est pourquoi vous obtenez toujours un résultat inattendu. Si vous souhaitez éviter ce problème, comparez toujours les mêmes variables de type signé (si les deux variables sont identiques, sinon, il n’y a pas de problème avec différents types signés également).

two's compliment of 1 ( assume int size is 2 Bytes )

0000 0000 0000 0001 (1 binary value)

1111 1111 1111 1110 (one's compliment)

1111 1111 1111 1111 (two's compliment) (cette valeur est 65535)

cette valeur replacing with -1 dans votre code.