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.
Esta pregunta ya tiene una respuesta aquí:
- Un acertijo (en C) 4 respuestas
- ¿Qué hay de malo en seguir el código C? [duplicado] 3 respuestas
- Confundido acerca de la expansión macro C y la aritmética de enteros [duplicado] 4 respuestas
- ¿Por qué falla la condición de bucle ''for''? [duplicado] 5 respuestas
- Impresión de elementos de matriz 6 respuestas
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:
-
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.
-
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.