-32768 no encaja en un valor firmado de 16 bits

Estoy usando PCLint v 9.00h

En mi código tengo lo siguiente (donde S16 es un bit firmado de 16 bits):

S16 temperatureResult = -32768; 

Que a menos que mi cerebro haya dejado de funcionar es el valor más pequeño que puede encajar en este tipo

Pero obtengo un error de pelusa de “Viola la regla 10.1 de MISRA 2004, conversión implícita de entero a tipo más pequeño”

Si cambio el valor a -32767 funciona bien.

¿Me estoy perdiendo algo obvio?

No necesariamente “no encaja”. Posiblemente encaja. (¿Realmente lo comprobaste?)

  • Si su plataforma utiliza int 32 bits (o mayor), entonces todas las expresiones aritméticas se evalúan en tipo int 32 bits y la advertencia simplemente le indica que está convirtiendo un valor int en un tipo más pequeño. PCLint simplemente no se molestó en comprobar si el valor real se ajusta al tipo de destino.

    Es posible que pueda suprimir esta advertencia con un tipo explícito de conversión

     S16 temperatureResult = (S16) -32768; 
  • Si su plataforma usa int 16 bits, entonces podría haber un problema ligeramente diferente aquí. En lenguaje C -32768 no es una constante atómica. -32768 es en realidad una expresión que consiste en un operador unario aplicado a una constante positiva 32768 . 32768 es una constante positiva que no se ajusta a un tipo de 16 bits, por lo que el comstackdor usa un tipo más grande (probablemente de 32 bits de long int ) para representar 32768 . En consecuencia, -32768 se evalúa en el dominio de un tipo más grande y también termina como un valor de tipo más grande. PCLind decidió advertirle sobre el cambio implícito a un tipo más grande. (Ver (-2147483648> 0) devuelve verdadero en C ++? Para más detalles).

    Si eso es lo que está sucediendo aquí, para evitar la advertencia, puede usar un tipo de conversión explícito

     S16 temperatureResult = (S16) -32768; 

    o, alternativamente, puede express la inicialización como

     S16 temperatureResult = -32767 - 1; 

    En este último caso, el comstackdor debería poder evaluar la expresión constante dentro del dominio de tipo int de 16 bits.

El estándar solo garantiza el rango de [-32767,32767] para corto firmado. Su implementación puede extenderse un poco, como la mayoría de las implementaciones, pero PCLint verifica el cumplimiento de los estándares.

En primer lugar: no tiene que lidiar con -32768 por estándar:

5.2.4.2.1 Tamaños de tipos enteros

[…]

– Valor mínimo para un objeto de tipo short int.

SHRT_MIN -32767 // – (215 – 1)

– valor máximo para un objeto de tipo short int

SHRT_MAX +32767 // 215 – 1

(Estoy buscando la parte que hace una nota definida por el entorno sobre el soporte de -32768 de todos modos)

Lo tengo:

La razón por la cual a veces hay un número compatible adicional se justifica por este párrafo:

6.2.6.2 tipos enteros

[…]

2 – Para los tipos de enteros con signo, los bits de la representación del objeto se dividirán en tres grupos: bits de valor, bits de relleno y el bit de signo. No es necesario que haya bits de relleno; debe haber exactamente un bit de signo. Cada bit que sea un bit de valor tendrá el mismo valor que el mismo bit en la representación del objeto del tipo sin signo correspondiente (si hay bits de valor M en el tipo con signo y N en el tipo sin signo, entonces M <= N). Si el bit de signo es cero, no afectará el valor resultante. Si el bit de signo es uno, el valor se modificará de una de las siguientes maneras:

– el valor correspondiente con el bit de signo 0 se anula (signo y magnitud);

– el bit de signo tiene el valor – (2N) (complemento de dos);

– el bit de signo tiene el valor – (2N – 1) (complemento de unos).

Cuál de estos se aplica a la implementación, como si el valor con el bit de signo 1 y todos los bits de valor cero (para los dos primeros), o con el bit de signo y todos los bits de valor 1 (para el complemento de unos), es una representación de trampa o un valor normal. En el caso de signo y magnitud y el complemento de unos, si esta representación es un valor normal, se llama cero negativo.

(Todo lo que cito está escrito en ISO / IEC 9899: TC3)

Me viene a la mente intentar:

S16 temperatureResult = (S16) 0x8000; // ASUME dos complementos enteros

El reparto explícito es porque la regla 10.1 dice

“El valor de una expresión de tipo entero no se convertirá implícitamente a un tipo subyacente diferente si …”

Hazlo portátil:

S16 temperatureResult = -32767-1;

Pero de todos modos, si MISRA requiere compatibilidad con las computadoras complementarias (como algunas supercomputadoras Cray), entonces el rango garantizado de 16 bits firmados es solo de [-32767 … 32767], por lo que no puede lograr lo que está tratando de hacer .