Eu tenho algum código C ++ que imprime um size_t
:
size_t a;
printf("%lu", a);
Eu gostaria que isso fosse compilado sem avisos nas arquiteturas de 32 e 64 bits.
Se fosse C99, eu poderia usar printf("%z", a);
. Mas AFAICT %z
não existe em nenhum dialeto C ++ padrão. Então, em vez disso, eu tenho que fazer
printf("%lu", (unsigned long) a);
o que é realmente feio.
Se não houver nenhum recurso para imprimir size_t
s embutidos na linguagem, eu me pergunto se é possível escrever um wrapper printf ou algum tal que insira os casts apropriados nos size_t
s de modo a eliminar avisos do compilador espúrios enquanto mantém os bons.
Alguma ideia?
Editar Para esclarecer por que estou usando printf: Tenho uma base de código relativamente grande que estou limpando. Ele usa printf wrappers para fazer coisas como "escrever um aviso, registrá-lo em um arquivo e, possivelmente, sair do código com um erro". Posso conseguir reunir C ++ - foo suficiente para fazer isso com um invólucro cout, mas prefiro não alterar todas as chamadas warn () no programa apenas para me livrar de alguns avisos do compilador.
"%l"
? Não será sempre do tamanho certo? Ou a portabilidade é importante?Respostas:
A maioria dos compiladores tem seu próprio especificador para
size_t
eptrdiff_t
argumentos, Visual C ++, por exemplo, usa% Iu e% Id respectivamente. Acho que o gcc permitirá que você use% zu e% zd.Você pode criar uma macro:
Uso:
fonte
%z
há suporte ou não, depende do tempo de execução, não do compilador. Usar__GNUC__
é, portanto, um pouco problemático, se você misturar GCC / mingw com msvcrt (e sem usar o printf aumentado de mingw).O
printf
especificador de formato%zu
funcionará bem em sistemas C ++; não há necessidade de torná-lo mais complicado.fonte
C ++ 11
C ++ 11 importa C99, portanto,
std::printf
deve oferecer suporte ao%zu
especificador de formato C99 .C ++ 98
Na maioria das plataformas,
size_t
euintptr_t
são equivalentes, caso em que você pode usar aPRIuPTR
macro definida em<cinttypes>
:Se você realmente deseja estar seguro, transmita
uintmax_t
e usePRIuMAX
:fonte
No Windows e na implementação do Visual Studio de printf
funciona para mim. ver msdn
fonte
VS 2008
também. Também tenha em mente que se pode usar%Id
,%Ix
e%IX
muito.Já que você está usando C ++, por que não usar IOStreams? Isso deve compilar sem avisos e fazer a coisa certa ciente do tipo, contanto que você não esteja usando uma implementação C ++ com morte cerebral que não defina um
operator <<
parasize_t
.Quando a saída real tiver que ser feita
printf()
, você ainda pode combiná-la com IOStreams para obter um comportamento de tipo seguro:Não é supereficiente, mas seu caso acima lida com E / S de arquivo, então esse é o seu gargalo, não este código de formatação de string.
fonte
std::stringstream
vez de fluxos IO.printf("x=%i, y=%i;\n", x, y);
vscout << "x=" << x << ", y=" << y << ";" << std::endl;
.aqui está uma solução possível, mas não é muito bonita ..
fonte
A biblioteca fmt fornece uma implementação portátil rápida (e segura) de
printf
incluir oz
modificador parasize_t
:Além disso, ele oferece suporte à sintaxe de string de formato semelhante ao Python e captura informações de tipo para que você não precise fornecê-las manualmente:
Ele foi testado com os principais compiladores e fornece saída consistente em todas as plataformas.
Isenção de responsabilidade : sou o autor desta biblioteca.
fonte
O tipo efetivo subjacente size_t é dependente da implementação . C Standard o define como o tipo retornado pelo operador sizeof; além de não ter sinal e ser uma espécie de tipo integral, o size_t pode ser praticamente qualquer coisa cujo tamanho pode acomodar o maior valor esperado para ser retornado por sizeof ().
Conseqüentemente, a string de formato a ser usada para size_t pode variar dependendo do servidor. Deve sempre ter o "u", mas pode ser l ou d ou talvez outra coisa ...
Um truque poderia ser convertê-lo no maior tipo integral da máquina, garantindo que não houvesse perda na conversão e, em seguida, usar a string de formato associada a esse tipo conhecido.
fonte
size_t
s para o maior tipo integral na máquina e usar a string de formato associada a esse tipo. Minha pergunta é: Existe uma maneira de fazer isso mantendo um código limpo (avisos apenas para erros de string de formato printf legítimo, sem conversão feia, etc.)? Eu poderia escrever um wrapper que mudasse a string de formato, mas o GCC não seria capaz de me dar avisos quando eu realmente baguncei minha string de formato.Posteriormente no código:
my::printf("test ", 1, '\t', 2.0);
fonte