¿Cómo formatea un int largo sin signo con printf?


379
#include <stdio.h>
int main() {
    unsigned long long int num = 285212672; //FYI: fits in 29 bits
    int normalInt = 5;
    printf("My number is %d bytes wide and its value is %ul. A normal number is %d.\n", sizeof(num), num, normalInt);
    return 0;
}

Salida:

My number is 8 bytes wide and its value is 285212672l. A normal number is 0.

Supongo que este resultado inesperado es de imprimir el unsigned long long int. ¿Cómo hacer que printf()una unsigned long long int?


2
Acabo de compilar su código (con% llu) con gcc y la salida fue la correcta. ¿Estás pasando alguna opción al compilador?
Juan

2
Tenga en cuenta que newlib de samsung bada parece no admitir "% lld": developer.bada.com/forum/…
RzR


Sugeriría usar stdint.h y ser explícito sobre el número de bits en su variable. Todavía estamos en un período de transición entre arquitecturas de 32 y 64 bits, y "unsigned long long int" no significa lo mismo en ambos.
BD en Rivenhill

Respuestas:


483

Use el modificador ll (el-el) long-long con la conversión u (sin signo). (Funciona en windows, GNU).

printf("%llu", 285212672);

11
O para ser precisos, es para GNU libc, y no funciona con el tiempo de ejecución C de Microsoft.
Mark Baker,

168
Esto no es una cosa de Linux / UNIX, el modificador de longitud "ll" se agregó al Estándar C en C99, si no funciona en "Microsoft C" es porque no cumplen con los estándares.
Robert Gamble

12
Funciona para mí en VS2008. Además, por lo que recuerdo, el compilador MS C (cuando está configurado para compilar C directo) se supone que cumple con C90 por diseño; C99 introdujo algunas cosas que no a todos les gustaban.
ス ー パ ー フ ァ ミ コ ン

66
Una cosa a tener en cuenta aquí es que si está pasando múltiples long longargumentos printfy usa el formato incorrecto para uno de ellos, digamos en %dlugar de %lld, entonces incluso los argumentos impresos después del incorrecto pueden estar completamente desactivados (o incluso pueden provocar printfun bloqueo ) Esencialmente, los argumentos variables se pasan a printf sin ningún tipo de información, por lo que si la cadena de formato es incorrecta, el resultado es impredecible.
dmitrii

1
Escuché a Herb Sutter decir en una entrevista que los clientes de Microsoft no piden C99, por lo que su compilador de C puro se ha congelado en C90. Eso se aplica si está compilando como C. Si compila como C ++, como otros han señalado anteriormente, debería estar bien.
ahcox

90

Es posible que desee probar el uso de la biblioteca inttypes.h que proporciona tipos, tales como int32_t, int64_t, uint64_tetc. A continuación, puede utilizar sus macros, tales como:

uint64_t x;
uint32_t y;

printf("x: %"PRId64", y: %"PRId32"\n", x, y);

Esto está "garantizado" para no darle el mismo problema long, unsigned long longetc., ya que no tiene que adivinar cuántos bits hay en cada tipo de datos.


donde estas PRId64, las PRId32macros definidas?
happy_marmoset

44
@happy_marmoset: se definen eninttypes.h
Nathan Fellman

44
Creo que necesitas PRIu64y PRIu32para enteros sin signo.
Lasse Kliemann

1
Es inttypes.hestándar? ¿No sería así stdint.h?
MD XF

2
Tenga en cuenta que estos tipos de ancho exacto son opcionales , ya que existen arquitecturas que no tienen tipos enteros de esos anchos exactos. Solo los tipos leastXy fastX(que en realidad pueden ser más anchos de lo indicado) son obligatorios.
DevSolar

78

%d-> para int

%u-> para unsigned int

%ld-> para long intolong

%lu-> para unsigned long into long unsigned intounsigned long

%lld-> para long long intolong long

%llu-> para unsigned long long intounsigned long long


¿Existe un especificador de formato como el número de dígitos para mostrar, justificación izquierda o derecha para% lld o% llu?
Asam Padeh

40

Por mucho tiempo (o __int64) usando MSVS, debe usar% I64d:

__int64 a;
time_t b;
...
fprintf(outFile,"%I64d,%I64d\n",a,b);    //I is capital i

37

Esto se debe a que% llu no funciona correctamente en Windows y% d no puede manejar enteros de 64 bits. Sugiero usar PRIu64 en su lugar y también encontrará que es portátil para Linux.

Intenta esto en su lugar:

#include <stdio.h>
#include <inttypes.h>

int main() {
    unsigned long long int num = 285212672; //FYI: fits in 29 bits
    int normalInt = 5;
    /* NOTE: PRIu64 is a preprocessor macro and thus should go outside the quoted string. */
    printf("My number is %d bytes wide and its value is %" PRIu64 ". A normal number is %d.\n", sizeof(num), num, normalInt);
    return 0;
}

Salida

My number is 8 bytes wide and its value is 285212672. A normal number is 5.

+1 para la referencia a PRIu64, que nunca había visto, pero esto no parece portátil para Linux de 64 bits (al menos) porque PRIu64 se expande a "lu" en lugar de "llu".
BD en Rivenhill

8
¿Y por qué eso sería malo? Un valor largo es de 64 bits en Linux de 64 bits, como en cualquier otro sistema operativo, excepto en Windows.
Timbre

@BDatRivenhill Linux / Unix usa LP64 en el que largo es de 64 bits
phuclv

1
Sin embargo, para que sea más portátil, utilice int64_ten su lugar porque es muy posible que algunas implementaciones, con mucho, mucho más grande que la de largo
phuclv

Esto debería a la cima! - una pequeña actualización: error: sufijo no válido en literal; C ++ 11 requiere un espacio entre el literal y el identificador [-Wreserved-user-defined-literal]
tofutim

14

En Linux es %lluy en Windows es%I64u

Aunque he descubierto que no funciona en Windows 2000, ¡parece que hay un error allí!


con Windows, (o al menos, con el compilador de Microsoft C para Windows) también hay% I64d,% I32u y% I32d
JustJeff

1
¿Qué tiene que ver con Windows 2000? La biblioteca C es la que maneja printf.
CMircea

1
Justo lo que observé. Escribí una aplicación que usaba esta construcción y funcionaba perfectamente en WinXP pero escupía basura en Win2k. Tal vez sea algo relacionado con una llamada al sistema que la biblioteca C está haciendo al núcleo, tal vez sea algo relacionado con Unicode, quién sabe. Recuerdo tener que solucionarlo usando _i64tot () o algo así.
Adam Pierce

77
Parece que la EM ejerce nuevamente su "libertad para innovar" ... ;-)
Dronz

El problema de Win2k / Win9x probablemente se deba a que el unsigned long longtipo de datos es relativamente nuevo (en ese momento, con el estándar C99) pero los compiladores de C (incluido MinGW / GCC) utilizan el antiguo tiempo de ejecución de Microsoft C que solo admitía la especificación C89. Solo tengo acceso a documentos API de Windows realmente antiguos y razonablemente recientes. Por lo tanto, es difícil decir exactamente cuándo I64use dejó caer el soporte. Pero suena como la era XP.
veganaiZe

8

Compílelo como x64 con VS2005:

% llu funciona bien.


3

Además de lo que la gente escribió hace años:

  • Es posible que obtenga este error en gcc / mingw:

main.c:30:3: warning: unknown conversion type character 'l' in format [-Wformat=]

printf("%llu\n", k);

Entonces, su versión de mingw no está predeterminada en c99. Añadir esta bandera del compilador: -std=c99.


3

Aparentemente, a nadie se le ha ocurrido una solución multiplataforma * durante más de una década desde [el] año 2008, por lo que añadiré la mía 😛. Por favor vota. (Bromeando. No me importa)

Solución: lltoa()

Cómo utilizar:

#include <stdlib.h> /* lltoa() */
// ...
char dummy[255];
printf("Over 4 bytes: %s\n", lltoa(5555555555, dummy, 10));
printf("Another one: %s\n", lltoa(15555555555, dummy, 10));

Ejemplo de OP:

#include <stdio.h>
#include <stdlib.h> /* lltoa() */

int main() {
    unsigned long long int num = 285212672; // fits in 29 bits
    char dummy[255];
    int normalInt = 5;
    printf("My number is %d bytes wide and its value is %s. "
        "A normal number is %d.\n", 
        sizeof(num), lltoa(num, dummy, 10), normalInt);
    return 0;
}

A diferencia de la %lldcadena de formato de impresión, esta funciona para mí con GCC de 32 bits en Windows.

*) Bueno, casi multiplataforma. En MSVC, aparentemente necesitas en _ui64toa()lugar de lltoa().


1
No tengo lltoa.
Antti Haapala

1

Las cosas no estándar son siempre extrañas :)

para la porción larga larga bajo GNU es L, lloq

y bajo ventanas creo que es llsolo


1

Maleficio:

printf("64bit: %llp", 0xffffffffffffffff);

Salida:

64bit: FFFFFFFFFFFFFFFF

¡Muy agradable!
Me

Pero, casi todos los compiladores de C ++ y C dan la advertencia: advertencia: uso del modificador de longitud 'll' con el carácter de tipo 'p' [-Wformat =]
Seshadri R

2
Esta respuesta completamente rota tiene un comportamiento doblemente indefinido y ni siquiera comienza a responder la pregunta .
Antti Haapala

@AnttiHaapala Dices que esta respuesta está completamente rota con un comportamiento doblemente indefinido, ¿puedes explicarlo o debo eliminarlo? ¿O mantenerlo como un buen mal ejemplo?
lama12345

0

Bueno, una forma es compilarlo como x64 con VS2008

Esto funciona como cabría esperar:

int normalInt = 5; 
unsigned long long int num=285212672;
printf(
    "My number is %d bytes wide and its value is %ul. 
    A normal number is %d \n", 
    sizeof(num), 
    num, 
    normalInt);

Para el código de 32 bits, necesitamos usar el especificador de formato __int64 correcto% I64u. Así se hace.

int normalInt = 5; 
unsigned __int64 num=285212672;
printf(
    "My number is %d bytes wide and its value is %I64u. 
    A normal number is %d", 
    sizeof(num),
    num, normalInt);

Este código funciona para el compilador VS de 32 y 64 bits.


Pruebe con un número real de 64 bits en lugar de '285212672' y no creo que el primer ejemplo se ejecute correctamente, compilado en cualquier destino.
Dyasta
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.