-32768 ne correspond pas à une valeur signée 16 bits

J’utilise PCLint v 9.00h

Dans mon code, j’ai les éléments suivants (où S16 est un 16 bits signé):

S16 temperatureResult = -32768; 

Ce qui, à moins que mon cerveau ait cessé de fonctionner, est la plus petite valeur pouvant entrer dans ce type

Mais je reçois une erreur de type “Viole MISRA 2004 Required Rule 10.1, Conversion implicite d’entier en type plus petit”

Si je modifie la valeur à -32767, cela fonctionne bien.

Est-ce que je manque quelque chose d’évident?

Ça ne veut pas forcément “pas fait”. Très probablement, ça va. (L’avez-vous réellement vérifié?)

  • Si votre plate-forme utilise un int 32 bits (ou plus), toutes les expressions arithmétiques sont évaluées en type int 32 bits et l’avertissement vous indique simplement que vous convertissez une valeur int en un type plus petit. PCLint n’a tout simplement pas pris la peine de vérifier si la valeur réelle correspond au type de destination.

    Vous pourrez peut-être supprimer cet avertissement avec un transtypage de type explicite

     S16 temperatureResult = (S16) -32768; 
  • Si votre plate-forme utilise un int 16 bits, un problème légèrement différent pourrait alors être impliqué. En langage C, -32768 n’est pas une constante atomique. -32768 est en fait une expression consistant en un opérateur unaire appliqué à une constante positive 32768 . 32768 est une constante positive qui ne rentre pas dans un type 16 bits, raison pour laquelle le compilateur utilise un type plus grand (probablement 32 bits de long int ) pour représenter 32768 . Par conséquent, -32768 est évalué dans le domaine d’un type plus grand et se termine également par une valeur de type plus grand. PCLind a décidé de vous avertir du passage implicite à un type plus grand. (Voir (-2147483648> 0) renvoie true en C ++? Pour plus de détails.)

    Si c’est ce qui se passe ici, alors pour éviter l’avertissement, vous pouvez utiliser un transtypage de type explicite.

     S16 temperatureResult = (S16) -32768; 

    ou, alternativement, vous pouvez exprimer l’initialisation sous la forme

     S16 temperatureResult = -32767 - 1; 

    Dans ce dernier cas, le compilateur devrait pouvoir évaluer l’expression constante dans le domaine de type int de 16 bits.

La norme ne garantit que la plage de [-32767,32767] pour les signatures signées. Votre implémentation peut s’étendre un peu, comme la plupart des implémentations, mais PCLint vérifie la conformité aux normes.

Tout d’abord: il n’a pas à traiter avec -32768 en standard:

5.2.4.2.1 Tailles des types entiers

[…]

– valeur minimale pour un object de type short int

SHRT_MIN -32767 // – (215 – 1)

– valeur maximale pour un object de type short int

SHRT_MAX +32767 // 215 – 1

(Je cherche la partie qui fait une note définie par l’environnement sur le support de -32768 de toute façon)

Je l’ai:

La raison pour laquelle il y a de toute façon parfois un ou plusieurs numéros supplémentaires est justifiée par ce paragraphe:

6.2.6.2 Types d’entiers

[…]

2 – Pour les types entiers signés, les bits de la représentation d’object doivent être divisés en trois groupes: les bits de valeur, les bits de remplissage et le bit de signe. Il n’y a pas besoin de bits de remplissage; il doit y avoir exactement un bit de signe. Chaque bit qui est un bit de valeur doit avoir la même valeur que le même bit dans la représentation d’object du type non signé correspondant (s’il y a M bits de valeur dans le type signé et N dans le type non signé, alors M <= N). Si le bit de signe est zéro, cela n'affectera pas la valeur résultante. Si le bit de signe est à un, la valeur doit être modifiée de l’une des manières suivantes:

– la valeur correspondante avec le bit de signe 0 est annulée (signe et magnitude);

– le bit de signe a la valeur – (2N) (complément à deux);

– le bit de signe a la valeur – (2N – 1) (complément à uns).

Laquelle de ces conditions est définie par l’implémentation, ainsi que la valeur avec le bit de signe 1 et tous les bits de valeur zéro (pour les deux premiers), ou avec le bit de signe et tous les bits de valeur 1 (pour le complément à un), est une représentation d’interruption ou une valeur normale. Dans le cas du signe et de la magnitude et du complément à 1, si cette représentation est une valeur normale, on l’appelle un zéro négatif.

(Tout ce que je cite est écrit dans ISO / IEC 9899: TC3)

Cela me vient à l’esprit d’essayer:

S16 temperatureResult = (S16) 0x8000; // ASSUMES deux entiers complémentaires

La dissortingbution explicite est parce que la règle 10.1 dit

“La valeur d’une expression de type entier ne doit pas être convertie implicitement en un type sous-jacent différent si …”

Rendez-le portable:

S16 temperatureResult = -32767 – 1;

Quoi qu’il en soit, si MISRA requirejs la compatibilité avec les ordinateurs complémentaires (comme certains supercalculateurs Cray), la plage garantie de signatures 16 bits signées est de seulement [-32767 … 32767]. Vous ne pouvez donc pas atteindre vos objectives. .