39 votes

Est-ce que le comportement "char foo = 255" n'est pas défini si char est signé?

La suite ne me donne aucun avertissement, que ce soit lors de la compilation avec gcc 4.5.2 sur x86 machine avec Linux:

char foo = 255;

Mais quand j'utilise -pedantic, gcc dit:

avertissement: débordement dans implicite de la constante de conversion

La façon de gcc actes est un peu étrange et il me fait douter si j'ai vraiment comprendre ce qui se passe dans cette mission. Je pense que si char 8 bits de long sur POSIX et il est signé par défaut, il ne peut pas détenir 255.

En C standard, il est dit que unsigned integer overflow résultats dans le débordement, mais signé de dépassement d'entier n'est pas défini. Alors, est-ce la cession comportement indéfini? Et pourquoi ne gcc agir de cette façon?

30voto

Keith Thompson Points 85120

Résumé: Le résultat est la mise en œuvre définies et très vraisemblablement -1, mais c'est compliqué, au moins en principe.

Les règles relatives à débordement sont différents pour les opérateurs contre les conversions, et pour les types signés vs non signé types -- et les règles de conversion changé entre C90 et C99.

Comme de C90, le débordement d'un opérateur ayant signé des opérandes entiers ("overflow" ce qui signifie que le résultat mathématique ne peut pas être représenté dans l'expression du type) a un comportement indéfini. Pour les opérandes entiers, le comportement est bien définie, comme d'habitude wraparound (strictement parlant, la norme n'appelle pas cela un "dépassement"). Mais votre déclaration:

char foo = 255;

ne pas utiliser toute les opérateurs (l' = est un initialiseur, pas une cession), de sorte que rien de tout ce qui s'applique dans ce cas.

Si le type char peut représenter la valeur 255 (ce qui est vrai soit de plain char n'est pas signée ou si CHAR_BIT >= 9), puis, bien sûr, le comportement est bien définie. L' int expression 255 est implicitement converti en char. (Depuis CHAR_BIT >= 8, il n'est pas possible pour ce cas particulier d'invoquer la non signé enveloppante.)

Sinon, la conversion, vous obtenez un résultat qui ne peut pas être stockée dans un char.

Comme de C90, le résultat de la conversion de la mise en œuvre est définie -- ce qui signifie qu'il est garanti à l'ensemble foo pour certains de la valeur au sein de la gamme de type char, et vous pouvez déterminer ce que cette valeur est par la lecture de la mise en œuvre de la documentation, qui est nécessaire pour vous raconter comment la conversion fonctionne. (Je n'ai jamais vu une mise en œuvre lorsque la valeur stockée est rien d'autre qu' -1, mais le résultat est en principe possible.)

C99 a changé la définition, de sorte qu'un débordement de conversion d'un type signé , soit des rendements de mise en œuvre définies par résultat ou soulève une mise en œuvre définies par le signal.

Si un compilateur choisit la seconde solution, alors il doit document signal est déclenché.

Donc ce qui se passe si une mise en œuvre définies par le signal est déclenché? La Section 7.14 de la norme dit:

L'ensemble des signaux, leur sémantique et leur valeur par défaut la manipulation de la mise en œuvre est définie par

Il n'est pas entièrement clair (pour moi) que la gamme de comportements possibles pour le "défaut de la manipulation de signaux. Dans le pire des cas, je suppose que ce signal pourrait mettre fin au programme. Vous pourrait ou ne pourrait pas être en mesure de définir un gestionnaire de signal qui capte le signal.

7.14 dit aussi:

Si la fonction retourne une valeur, si la valeur de sig est SIGFPE, SIGILL, SIGSEGV, ou de toute autre mise en valeur définie correspondant à un calcul d'exception, le comportement est indéfini; sinon le programme va reprendre l'exécution à l'endroit ou elle a été interrompu.

mais je ne pense que ce qui s'applique, depuis un débordement de conversion n'est pas un "calcul d'exception", car le terme est utilisé ici. (À moins que la mise en œuvre définies par le signal qui arrive à être SIGFPE, SIGILLou SIGSEGV - mais ce serait ridicule).

Donc, en fin de compte, si une mise en œuvre choisit d'élever un signal en réponse à un débordement de conversion, le comportement (et pas seulement le résultat) est au moins de mise en œuvre définis, et il pourrait y avoir des circonstances dans lesquelles il pourrait être indéfini. En tout cas, il ne semble pas être n'importe quel portable façon de traiter avec un tel signal.

Dans la pratique, je n'ai jamais entendu parler d'une application qui tire parti de la nouvelle formulation du C99. Pour tous les compilateurs j'ai entendu, le résultat de la conversion est mise en œuvre définies-et très probablement les rendements de ce que vous attendez d'un 2-complément de troncature. (Et je ne suis pas du tout convaincu que ce changement dans C99 était une bonne idée. Si rien d'autre, il fait cette réponse environ 3 fois plus longtemps qu'elle serait autrement nécessaire.)

13voto

AndreyT Points 139512

Entier signé de débordement provoque un comportement indéfini uniquement lorsque cela se produit lors de l'évaluation des résultats intermédiaires des expressions arithmétiques, par exemple, au cours de binaire mutiplication, unaire décrémenter etc. Aussi, la conversion en virgule flottante valeur de type entier provoque un comportement indéfini si la valeur est hors de portée.

Un débordement partie intégrante de conversion de type signé ne cause pas un comportement indéfini. Au lieu de cela, elle produit de la mise en œuvre définies par résultat (avec la possibilité d'une mise en œuvre définies par le signal étant élevé).

9voto

Kerrek SB Points 194696

Selon C11, 6.3.1.3:

Lorsqu'une valeur de type entier est convertie en un type entier autre que _Bool , si le [...] nouveau type est signé et que la valeur ne peut y être représentée; soit le résultat est défini par l'implémentation, soit un signal défini par l'implémentation est émis.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X