Quero trabalhar de forma portável com tipos assinados de 64 bits em C. No entanto, sei que int64_t
não há garantia de que isso seja definido. Posso usar alguma mágica do pré-processador na geração do meu sistema de construção (por exemplo, CMake's check_type_size()
) para obter definições do pré-processador me dizendo se posso usá-lo ou não. No entanto, temos o PRId64
especificador de formato, que devemos usar para passar int64_t
valores para printf()
funções semelhantes a . Posso, portanto, usar a definição de PRId64
como um proxy para determinar se está ou não int64_t
disponível?
Você pode testar a existência de macros opcionais que podem ser fornecidas por
<stdint.h>
, comoINT64_MIN
ouINT64_MAX
que são definidas se e somente se os tipos opcionais correspondentes, como,int64_t
forem implementados.De C99 §7.18 par. 4, e C11/C17 §7.20 par. 4, e C23 §7.22.1 par. 4:
Atualmente, o padrão não exige que a
PRId64
macro não seja definida por<inttypes.h>
seint64_t
não for implementada, e o mesmo ocorre para os outros tipos opcionais definidos por<stdint.h>
.Resumindo:
defined(INT64_MIN)
se e somente seint64_t
for implementadodefined(PRId64)
não implicaint64_t
que seja implementado!defined(PRId64)
implicaint64_t
não é implementadoSim, mas...
É realmente um proxy para esse propósito. O padrão tem o seguinte a dizer
<inttypes.h>
em 7.8.1:"Hospedado" aqui se refere a sistemas com sistemas operacionais; então sim, você pode usar a macro para detectar a presença dos tipos correspondentes em ambientes hospedados. Observe que uma implementação compatível com C99 poderia definir as macros de formato printf e scanf sem
int64_t
estarem presentes (conforme apontado por Ian Abbott), embora isso pareça um cenário bastante absurdo. Se, por outro lado, você planeja executar o código (ou oferecer suporte à execução dele) em ambientes não hospedados, como plataformas embarcadas ou kernels, você não deve usar,<inttypes.h>
pois esse cabeçalho pode não estar disponível. Então, o que você pode usar em vez disso?int64_t
/uint64_t
são chamados de "inteiros de largura exata" no padrão e são definidos em 7.22.2.2 (C23) e 7.18.1.1 (C99). O seguinte pode ser encontrado no rascunho do padrão C23 sob a especificação de<stdint.h>
:Em C99, as macros de largura não são especificadas; pode-se usar as macros de limite descritas em 7.18.2.1 em vez disso. Essas macros têm uma ressalva semelhante às macros C23, encontradas no parágrafo 4 de 7.18.
Ou seja, você pode usar as macros definidas no cabeçalho que
typedef
são os tipos em primeiro lugar. Por exemplo,INT64_WIDTH
eUINT64_MIN
.