Size_t independente de plataforma Especificadores de formato em c?

86

Quero imprimir uma variável do tipo size_tem C, mas parece que size_ttem um alias para diferentes tipos de variáveis ​​em diferentes arquiteturas. Por exemplo, em uma máquina (64 bits), o código a seguir não emite nenhum aviso:

size_t size = 1;
printf("the size is %ld", size);

mas na minha outra máquina (32 bits), o código acima produz a seguinte mensagem de aviso:

aviso: o formato '% ld' espera o tipo 'long int *', mas o argumento 3 tem o tipo 'size_t *'

Suspeito que isso seja devido à diferença no tamanho do ponteiro, de modo que na minha máquina de 64 bits o size_talias é a long int( "%ld"), enquanto na minha máquina de 32 bits o size_talias é outro tipo.

Existe um especificador de formato especificamente para size_t?

Ethan Heilman
fonte
Sua mensagem de aviso não corresponde ao código. O aviso menciona ponteiros, seu código não tem nenhum. Você removeu algum &em algum lugar?
Jens,
Ponteiros? Não, não recebo nenhum aviso sobre ponteiros; na verdade, dependendo da máquina em que executo o código, às vezes não recebo nenhum aviso. Tente o seguinte código de teste: #include <stdio.h> int main () {size_t size = 1; printf ("o tamanho é% ld", tamanho); return 0; }
Ethan Heilman
1
@EthanHeilman Ele está se referindo ao fato de que seus avisos dizem warning: format '%ld' expects type 'long int *', but argument 3 has type 'size_t *'quando provavelmente deveriam estar dizendo warning: format '%ld' expects type 'long int', but argument 3 has type 'size_t'. Você estava usando scanf()quando recebeu esses avisos?
RastaJedi de

Respostas:

123

Sim: use o zmodificador de comprimento:

size_t size = sizeof(char);
printf("the size is %zu\n", size);  // decimal size_t ("u" for unsigned)
printf("the size is %zx\n", size);  // hex size_t

Os outros modificadores de comprimento disponíveis são hh(para char), h(para short), l(para long), ll(para long long), j(para intmax_t), t(para ptrdiff_t) e L(para long double). Consulte §7.19.6.1 (7) da norma C99.

Adam Rosenfield
fonte
qual é a diferença entre zd e zu? Eu entendo que zd é decimal, mas é assinado, em caso afirmativo como zd sendo assinado afeta as coisas.
Ethan Heilman
1
É a diferença entre um size_te um ssize_t; o último raramente é usado.
Adam Rosenfield
26
Certo, então, neste caso, você deve usar %zu, porque o argumento não tem sinal.
caf
As outras opções disponíveis são explicadas na página de manual do printf: linux.die.net/man/3/printf
INS
9
@detly: Não, o zmodificador de comprimento não faz parte do C89 / C90. Se você está visando um código compatível com C89, o melhor que você pode fazer é lançar unsigned longe usar o lmodificador de comprimento, por exemplo printf("the size is %lu\n", (unsigned long)size);; suportar C89 e sistemas com size_tmaior do que longé mais complicado e exigiria o uso de uma série de macros de pré-processador.
Adam Rosenfield
45

Sim existe. É %zu(conforme especificado em ANSI C99).

size_t size = 1;
printf("the size is %zu", size);

Observe que size_tnão tem sinal, portanto, %ldé duplamente errado: modificador de comprimento errado e especificador de conversão de formato errado. Caso você se pergunte, %zdé para ssize_t(que está assinado).

maxschlepzig
fonte
1

MSDN , afirma que o Visual Studio oferece suporte ao prefixo "I" para código portátil em plataformas de 32 e 64 bits.

size_t size = 10;
printf("size is %Iu", size);
Arkantos
fonte
6
é específico do MS, que não está em conformidade com o padrão, então não é independente de plataforma
phuclv
@phuclv De fato. E se realmente diz - como a resposta sugere - 'portátil', é ainda pior do que eu jamais soube sobre a esclerose múltipla. Não que isso fosse me surpreender ... Eu não sou do tipo que votou negativamente porque alguém se esforçou para tentar responder algo, mas ainda assim essa resposta está errada. Ah, acho que entendi a ideia aqui em 'portátil'. Deve-se dizer que funciona tanto para 32 bits quanto para 64 bits. Mas é claro que sim.
Pryftan