Estou tentando imprimir tipos como off_t
e size_t
. Qual é o espaço reservado correto para printf()
isso é portátil ?
Ou existe uma maneira completamente diferente de imprimir essas variáveis?
Estou tentando imprimir tipos como off_t
e size_t
. Qual é o espaço reservado correto para printf()
isso é portátil ?
Ou existe uma maneira completamente diferente de imprimir essas variáveis?
Respostas:
Você pode usar z
para size_t e t
ptrdiff_t como em
printf("%zu %td", size, ptrdiff);
Mas minha página de manual diz que algumas bibliotecas mais antigas usavam um caractere diferente z
e desencorajam o uso dele. No entanto, é padronizado (pelo padrão C99). Para aqueles intmax_t
e int8_t
de stdint.h
e assim por diante, existem macros que você pode usar, como outra resposta disse:
printf("value: %" PRId32, some_int32_t);
printf("value: %" PRIu16, some_uint16_t);
Eles estão listados na página de manual inttypes.h
.
Pessoalmente, eu apenas converteria os valores unsigned long
ou long
gostaria que outra resposta recomendasse. Se você usa o C99, pode (e deve) transmitir para unsigned long long
ou long long
usar os formatos %llu
ou %lld
, respectivamente.
%zd
com a size_t
é um comportamento indefinido devido à incompatibilidade de assinatura (C99 7.19.6.1 # 9). Deve ser %zu
.
%zd
com um size_t
comportamento indefinido, é obtido desse parágrafo ou de qualquer outro. De fato, a definição de %z
# 7 permite explicitamente %d
com size_t
e o tipo assinado correspondente, e §6.2.5 # 9 permite explicitamente o uso de valores de tipos não assinados onde o tipo assinado correspondente é esperado, desde que o valor seja um valor não negativo válido do tipo assinado.
Para imprimir off_t
:
printf("%jd\n", (intmax_t)x);
Para imprimir size_t
:
printf("%zu\n", x);
Para imprimir ssize_t
:
printf("%zd\n", x);
Consulte 7.19.6.1/7 no padrão C99 ou a documentação mais conveniente do POSIX sobre códigos de formatação:
http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html
Se sua implementação não suportar esses códigos de formatação (por exemplo, porque você está no C89), você tem um problema, já que no AFAIK não há tipos de número inteiro no C89 que possuam códigos de formatação e que sejam tão grandes como esses tipos. Então, você precisa fazer algo específico da implementação.
Por exemplo, se o seu compilador tiver long long
e a sua biblioteca padrão suportar %lld
, você pode esperar com confiança que isso servirá no lugar de intmax_t
. Mas, se isso não acontecer, você precisará recorrer long
, o que falharia em algumas outras implementações porque é muito pequeno.
ssize_t
tenha o mesmo tamanho que size_t
, portanto, um código verdadeiramente portátil deve convertê-lo intmax_t
e imprimir com o %jd
mesmo valor off_t
.
Para a Microsoft, a resposta é diferente. O VS2013 é amplamente compatível com C99, mas "[h] os prefixos hh, j, z e comprimento não são suportados". Para size_t ", ou seja, __int32 não assinado em plataformas de 32 bits, __int64 não assinado em plataformas de 64 bits" use o prefixo I (maiúscula) com o especificador de tipo o, u, x ou X. Consulte a especificação de tamanho do VS2013
Quanto a off_t, é definido desde que VC \ include \ sys \ types.h.
off_t
é sempre o long
que tornaria 32 bits (até o Windows de 64 bits usa 32 bits para long
).
Qual versão do C você está usando?
Em C90, a prática padrão é converter em assinado ou não assinado por muito tempo, conforme apropriado, e imprimir em conformidade. Eu já vi% z para size_t, mas Harbison e Steele não mencionam isso em printf () e, de qualquer forma, isso não ajudaria você com ptrdiff_t ou o que seja.
No C99, os vários tipos _t vêm com suas próprias macros printf, então algo como "Size is " FOO " bytes."
eu não sei detalhes, mas isso faz parte de um formato numérico bastante grande que inclui o arquivo.
Você desejará usar as macros de formatação de inttypes.h.
Veja esta pergunta: Cadeia de caracteres de formato de plataforma cruzada para variáveis do tipo size_t?
off_t
tipo é maior que um ponteiro em qualquer sistema de 32 bits que suporte arquivos grandes (que é a maioria dos sistemas de 32 bits atualmente).
Olhando para man 3 printf
Linux, OS X e OpenBSD, todos mostram suporte %z
para size_t
e %t
para ptrdiff_t
(para C99), mas nenhum deles menciona off_t
. Sugestões em geral geralmente oferecem a %u
conversão para off_t
, que é "correta o suficiente", tanto quanto eu sei (ambas unsigned int
e off_t
variam de forma idêntica entre os sistemas de 64 e 32 bits).
unsigned int
e 64 bits off_t
. Portanto, o elenco causaria a perda de dados.
Vi este post pelo menos duas vezes, porque a resposta aceita é difícil de lembrar para mim (raramente uso z
ou j
sinalizadores e eles parecem não ser independentes da plataforma ).
O padrão nunca indica claramente o tamanho exato dos dados size_t
, por isso sugiro que você verifique primeiro o comprimento size_t
na sua plataforma e selecione um deles:
if sizeof(size_t) == 4 use PRIu32
if sizeof(size_t) == 8 use PRIu64
E sugiro usar stdint
tipos em vez de tipos de dados brutos para garantir a consistência.
%zu
pode ser usado para imprimir size_t
valores. Definitivamente, não se deve recorrer ao uso de um especificador uint32_t
/ uint64_t
format para imprimir um size_t
, pois não há garantia de que esses tipos sejam compatíveis.
Pelo que me lembro, a única maneira portátil de fazê-lo, é converter o resultado em "int longo não assinado" e usá-lo %lu
.
printf("sizeof(int) = %lu", (unsigned long) sizeof(int));
long long
não existe no padrão C ++ e, portanto, é inerentemente não portátil.
fopen
,fseek
etc. no Mac OS X.off_t
é utilizado para o deslocamento.