2012-05-19 31 views
10

Tengo un problema al utilizar la función printf para imprimir valores de tipo unsigned long long intimpresión unsigned long long int Tipo Valor Devuelve resultados extraños

no tengo idea de lo que está mal. Estoy usando Dev-Cpp 4.9.9.2 y Visual Studio 2010 Professional (sé que no es un compilador de C, pero de todos modos, quería probar) en Windows 7 Professional de 64 bits. Para la visualización, solía %llu modificador (según How do you printf an unsigned long long int(the format specifier for unsigned long long int)?), pero también he intentado I64d sin efecto ...


En primer lugar, sólo quería imprimir valor mínimo y máximo de unsigned long long int (usando ULONG_MAX de limits.h)

printf("unsigned long long int: \n%llu to %llu \n\n", 0, ULONG_MAX); 

Devuelve:

unsigned long long int: 18446744069414584320-1580552164021 (Dev-Cpp)

unsigned long long int: 18446744069414584320 a 0 (Visual Studio)


Luego trató de usar printf imprimir dos ceros

printf("unsigned long long int: \n%llu to %llu \n\n", 0, 0); 

Devoluciones:

unsigned long long int: 0 a 1580552164021 (Dev-Cpp)

unsigned long long int: 0 a 0 (Visual Studio)


trataron también dos ULONG_MAX valores

printf("unsigned long long int: \n%llu to %llu \n\n", ULONG_MAX, ULONG_MAX); 

Devoluciones:

unsigned long long int: 18446744073709551615-1580552164021 (Dev-Cpp)

unsigned long long int: 18446744073709551615-0 (Visual Studio)


¿Por qué se comporta así? ¿Podrías explicarme eso?

Respuesta

11

Esto está mal:

printf("unsigned long long int: \n%llu to %llu \n\n", 0, ULONG_MAX); 

utiliza un especificador unsigned long long formato, pero se pasa un int y un valor unsigned long. Las reglas de promoción significan que puede ser descuidado para todo int -gramo o más pequeño, lo que hace no se aplica a long long.

Uso arroja:

printf("unsigned long long int: \n%llu to %llu \n\n", 
     0ULL, (unsigned long long) ULONG_MAX); 

Explicación: Al pasar argumentos a printf, cualquier tipo que pueda caber en una int es ascendido a int, y después de cualquier tipo que pueda caber en una unsigned int es ascendido a unsigned int. También está bien pasar un tipo sin firmar a un especificador de formato con signo o viceversa, siempre que el valor pasado se pueda representar utilizando el tipo especificado por el especificador de formato.

Así que hay que tener cuidado con long y long long, pero puede ser descuidado con int, short y char.

La mayoría de los compiladores tienen configuraciones para advertirle sobre este tipo de error, ya que se puede detectar en tiempo de compilación bastante fácilmente; GCC y Clang tienen -Wformat que se traduce en las siguientes advertencias:

 
test.c:5: warning: format ‘%llu’ expects type ‘long long unsigned int’, but argument 2 has type ‘int’ 
test.c:5: warning: format ‘%llu’ expects type ‘long long unsigned int’, but argument 3 has type ‘long unsigned int’ 
+0

0 es int, no largo. –

+1

Eso fue descuidado. –

10

Usted no está pasando unsigned long longs. Está pasando un int (0) y unsigned long (ULONG_MAX). Debe pasar al printf() exactamente lo que promete pasar en la cadena de formato.

Tal vez puedas probar:

printf("unsigned long long int: \n%llu to %llu \n\n", 0ULL, (unsigned long long)ULONG_MAX); 
4

ULONG_MAX se refiere a unsigned long y no a unsigned long long. Para este último, use ULLONG_MAX (tenga en cuenta el L adicional).

es necesario cambiar los printf() llamadas así:

printf("unsigned long long int: \n%llu to %llu \n\n", 0ULL, ULLONG_MAX); 
printf("unsigned long long int: \n%llu to %llu \n\n", ULLONG_MAX, ULLONG_MAX); 

Esto asegura que los argumentos a printf() coinciden con los especificadores de formato.

0

largo int larga es un tipo de la norma C99, MSVC no admite esta. Tome un compilador con soporte C99 (como MinGW para Windows) y funcionará.

+1

MSVC es compatible con 'long long' a pesar de no admitir completamente C99. –