Por que as novas strings de opção de formato printf() (específicas para largura de bits) não foram adotadas como parte do C99?

StackOverflow https://stackoverflow.com/questions/1183679

Pergunta

Enquanto pesquisava como fazer cross-plataforma printf() formatar strings em C (ou seja, levando em consideração o número de bits que espero que cada argumento inteiro printf() deveria ser) eu encontrei esta seção do artigo da Wikipedia sobre printf().O artigo discute opções não padrão que podem ser passadas para printf() strings de formato, como (o que parece ser uma extensão específica da Microsoft):

printf("%I32d\n", my32bitInt);

Prossegue afirmando que:

O ISO C99 inclui o arquivo de cabeçalho Inttypes.h que inclui várias macros para uso na codificação PrintF independente da plataforma.

...e então lista um conjunto de macros que podem ser encontradas no referido cabeçalho.Olhando para o arquivo de cabeçalho, para usá-los eu teria que escrever:

 printf("%"PRId32"\n", my32bitInt);

Minha pergunta é:estou esquecendo de algo?Esta é realmente a maneira padrão do C99 de fazer isso?Se sim, por quê?(Embora eu não esteja surpreso por nunca ter visto código que usa strings de formato dessa maneira, já que parece tão complicado...)

Foi útil?

Solução

A lógica C parece implicar queu003Cinttypes.h> está padronizando a prática existente:

u003Cinttypes.h> foi derivado do cabeçalho do mesmo nome encontrado em vários sistemas existentes de 64 bits.

Mas o restante do texto não escreve sobre essas macros, e não me lembro que eles eram práticas existentes na época.

O que se segue é apenas especulação, mas educado pela experiência de como os comitês de padronização funcionam.

Uma vantagem das macros C99 sobre a padronização do especificador de formato adicional para Printf (observe que o C99 também adicionou alguns) é que o fornecimento <inttypes.h> e <stdint.h> Quando você já possui uma implementação que suporta os recursos necessários de uma maneira específica de implementação, é apenas escrever dois arquivos com typedef e macros adequados. Isso reduz o custo de tornar em conformidade a implementação existente, reduz o risco de quebrar os programas existentes que fizeram uso dos recursos específicos de implementação existentes (a maneira padrão não interfere) e facilita a porte de programas conformantes para a implementação que não os possuem Cabeçalhos (eles podem ser fornecidos pelo programa). Além disso, se as formas específicas da implementação já variaram na época, ela não favorece uma implementação em detrimento de outra.

Outras dicas

Correto, é assim que o padrão C99 diz que você deve usá-los.Se você deseja um código verdadeiramente portátil que seja 100% compatível com os padrões ao pé da letra, você deve sempre imprimir um int usando "%d" e um int32_t usando "%"PRId32.

A maioria das pessoas não se incomodará, pois há muito poucos casos em que não fazer isso seria importante.A menos que você esteja portando seu código para Win16 ou DOS, você pode assumir que sizeof(int32_t) <= sizeof(int), então é inofensivo imprimir acidentalmente um int32_t como um int.Da mesma forma, um long long é praticamente universalmente de 64 bits (embora não seja garantido que seja), então imprimir um int64_t como um long long (por exemplo.com um %llx especificador) também é seguro.

Os tipos int_fast32_t, int_least32_t, et al quase nunca são usados, então você pode imaginar que seus especificadores de formato correspondentes são usados ​​ainda mais raramente.

Você sempre pode lançar para cima e usar %jd qual é o intmax_t Especificador de formato.

printf("%jd\n", (intmax_t)(-2));

eu usei intmax_t para mostrar que qualquer intXX_t pode ser usado, mas simplesmente lançando para long é muito melhor para o int32_t caso, então use %ld.

Só posso especular sobre o porquê.Gosto da resposta do AProgrammer acima, mas há um aspecto esquecido: o que você adicionará ao printf como modificador de formato? Já existem duas maneiras diferentes de usar números em uma string de formato printf (largura e precisão).Adicionar um terceiro tipo de número para dizer quantos bits de precisão existem no argumento seria ótimo, mas onde você vai colocá-lo sem confundir as pessoas?Infelizmente, uma das falhas do C é que printf não foi projetado para ser extensível.

As macros são horríveis, mas quando você precisa escrever código portátil em plataformas de 32 e 64 bits, elas são uma dádiva de Deus.Definitivamente salvou meu bacon.

Acho que a resposta para sua pergunta por que é também

  • Ninguém poderia pensar em uma maneira melhor de fazer isso, ou
  • O comitê de padrões não conseguiu chegar a um acordo sobre nada que considerasse claramente melhor.

Outra possibilidade: compatibilidade com versões anteriores. Se você adicionar mais especificadores de formato a printf, ou opções adicionais, é possível que um especificador em algum código pré-C99 tenha uma sequência de formato interpretada de maneira diferente.

Com a mudança C99, você não está mudando a funcionalidade de printf.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top