type long float data c loops integer sizeof negative-number

long - El bucle que comienza en-1 no imprime nada



int float char (3)

Las operaciones binarias entre diferentes tipos integrales se realizan dentro de un tipo "común" definido por las llamadas conversiones aritméticas habituales. Entonces int d es de tipo chamuscado inicializado con valor -1. Que cuando se convierte en unsigned int devolverá un máximo de unsigned int, que es mucho mayor que el valor devuelto por TOTAL_ELEMENTS.

Se supone que este programa imprime los elementos de la array , pero cuando se ejecuta, no se muestra ningún resultado.

#include <stdio.h> #define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0])) int array[] = { 23, 34, 12, 17, 204, 99, 16 }; int main() { int d; for (d = -1; d <= (TOTAL_ELEMENTS - 2); d++) printf("%d/n", array[d + 1]); return 0; }

¿Por qué este programa no muestra ningún resultado?


Mi gcc genera esta advertencia:

warning: comparison of integers of different signs: ''int'' and ''unsigned long'' [-Wsign-compare] for(d = 0; d < TOTAL_ELEMENTS; d++)

lo que significa que (TOTAL_ELEMENTS-2) unsigned int está unsigned int mientras que d está signed int . Esto hace que la expresión siempre sea false para el valor inicial de d , ya que (unsigned int)(-1) > (TOTAL_ELEMENTS-2) .


sizeof devuelve un entero sin signo, por lo que TOTAL_ELEMENTS también está sin signo.

d está firmado. Inicialmente, d es -1 . Sin embargo, al hacer la comparación, d está implícitamente encasillado en unsigned, por lo que ya no es -1 cuando se compara con TOTAL_ELEMENTS , en realidad es UINT_MAX (que es 4294967295 en mi máquina, pero puede diferir para otros).

También,

Si quieres arreglar esto, TOTAL_ELEMENTS en int :

for(d = -1; d <= (int)(TOTAL_ELEMENTS - 2); d++)

Esto imprimirá:

23 34 12 17 204 99 16

Como era de esperar También puede consultar la operación de comparación en enteros sin signo y con signo para obtener más información sobre el tema de las comparaciones con signo sin signo.

Vale la pena señalar que activar las advertencias del compilador lo habría ayudado a descubrir lo que estaba sucediendo (como observó Hyde en su comment ):

$ gcc -Wall -Wextra test.c test.c:7:17: warning: comparison of integers of different signs: ''int'' and ''unsigned long'' [-Wsign-compare] for(d = 0; d < TOTAL_ELEMENTS; d++) ~ ^ ~~~~~~~~~~~~~~ 1 warning generated.

Alternativamente, ¿por qué no comenzar d en 0 y ejecutar TOTAL_ELEMENTS - 1 lugar? Incluso puede soltar la conversión de texto, que es necesaria solo para el caso de esquina de d = -1 .

for(d = 0; d < TOTAL_ELEMENTS; d++) printf("%d/n", array[d]);

Como nota al pie, aquí están los extractos relevantes del Estándar C99:

  1. 6.3.1.8p2 define la conversión de tipo con signo a sin signo.

    Si el operando que tiene un tipo entero sin signo tiene un rango mayor o igual al rango del tipo del otro operando, entonces el operando con tipo entero con signo se convierte en el tipo del operando con tipo entero sin signo.

  2. 6.3.1.3p2 define cómo se realiza la conversión: agregando UINT_MAX + 1 a la representación firmada.

    Si el nuevo tipo no tiene signo, el valor se convierte al sumar o restar repetidamente uno más que el valor máximo que se puede representar en el nuevo tipo hasta que el valor esté en el rango del nuevo tipo.

    Entonces -1 => -1 + (UINT_MAX + 1) = UINT_MAX , para este escenario.