Cómo imprimir de forma portátil un tipo int64_t en C
El estándar C99 tiene tipos de números enteros con tamaño de bytes como int64_t. %I64d
Actualmente estoy usando el formato de Windows (o sin firmar %I64u
), como:
#include <stdio.h>
#include <stdint.h>
int64_t my_int = 999999999999999999;
printf("This is my_int: %I64d\n", my_int);
y recibo esta advertencia del compilador:
warning: format ‘%I64d’ expects type ‘int’, but argument 2 has type ‘int64_t’
Lo intenté con:
printf("This is my_int: %lld\n", my_int); // long long decimal
Pero recibo la misma advertencia. Estoy usando este compilador:
~/dev/c$ cc -v
Using built-in specs.
Target: i686-apple-darwin10
Configured with: /var/tmp/gcc/gcc-5664~89/src/configure --disable-checking --enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib --build=i686-apple-darwin10 --program-prefix=i686-apple-darwin10- --host=x86_64-apple-darwin10 --target=i686-apple-darwin10 --with-gxx-include-dir=/include/c++/4.2.1
Thread model: posix
gcc version 4.2.1 (Apple Inc. build 5664)
¿Qué formato debo usar para imprimir la variable my_int sin recibir una advertencia?
Por int64_t
tipo:
#include <inttypes.h>
int64_t t;
printf("%" PRId64 "\n", t);
por uint64_t
tipo:
#include <inttypes.h>
uint64_t t;
printf("%" PRIu64 "\n", t);
También puedes utilizar PRIx64
para imprimir en hexadecimal.
cppreference.com tiene una lista completa de macros disponibles para todos los tipos, incluida intptr_t
( PRIxPTR
). Hay macros independientes para scanf, como SCNd64
.
Una definición típica de PRIu16 sería "hu"
, por lo que la concatenación implícita de constantes de cadena ocurre en el momento de la compilación.
Para que su código sea completamente portátil, debe usar PRId32
etc para imprimir int32_t
y "%d"
similares para imprimir int
.
La forma C99 es
#include <inttypes.h>
int64_t my_int = 999999999999999999;
printf("%" PRId64 "\n", my_int);
¡O podrías lanzar!
printf("%ld", (long)my_int);
printf("%lld", (long long)my_int); /* C89 didn't define `long long` */
printf("%f", (double)my_int);
Si está atascado con una implementación de C89 (en particular, Visual Studio), tal vez pueda usar un código abierto <inttypes.h>
(y <stdint.h>
): http://code.google.com/p/msinttypes/
Con C99, el %j
modificador de longitud también se puede utilizar con la familia de funciones printf para imprimir valores de tipo int64_t
y uint64_t
:
#include <stdio.h>
#include <stdint.h>
int main(int argc, char *argv[])
{
int64_t a = 1LL << 63;
uint64_t b = 1ULL << 63;
printf("a=%jd (0x%jx)\n", a, a);
printf("b=%ju (0x%jx)\n", b, b);
return 0;
}
La compilación de este código gcc -Wall -pedantic -std=c99
no genera advertencias y el programa imprime el resultado esperado:
a=-9223372036854775808 (0x8000000000000000)
b=9223372036854775808 (0x8000000000000000)
Esto es de acuerdo con printf(3)
mi sistema Linux (la página de manual dice específicamente que j
se usa para indicar una conversión a intmax_t
or uintmax_t
; en mi stdint.h, ambos int64_t
y intmax_t
están tipificados exactamente de la misma manera, y de manera similar para uint64_t
). No estoy seguro de si esto es perfectamente portátil a otros sistemas.
Viniendo del mundo integrado, donde incluso uclibc no siempre está disponible y códigos como
uint64_t myval = 0xdeadfacedeadbeef;
printf("%llx", myval);
¿Estás imprimiendo una mierda o no funciona en absoluto? Siempre uso un pequeño ayudante que me permite volcar correctamente uint64_t hexadecimal:
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
char* ullx(uint64_t val)
{
static char buf[34] = { [0 ... 33] = 0 };
char* out = &buf[33];
uint64_t hval = val;
unsigned int hbase = 16;
do {
*out = "0123456789abcdef"[hval % hbase];
--out;
hval /= hbase;
} while(hval);
*out-- = 'x', *out = '0';
return out;
}