J'ai du code C ++ qui imprime un size_t
:
size_t a;
printf("%lu", a);
J'aimerais que cela compile sans avertissements sur les architectures 32 et 64 bits.
Si c'était C99, je pourrais utiliser printf("%z", a);
. Mais AFAICT %z
n'existe dans aucun dialecte C ++ standard. Alors à la place, je dois faire
printf("%lu", (unsigned long) a);
ce qui est vraiment moche.
S'il n'y a pas de fonction d'impression size_t
intégrée dans le langage, je me demande s'il est possible d'écrire un wrapper printf ou quelque chose de ce genre qui insérera les moulages appropriés sursize_t
s afin d'éliminer les faux avertissements du compilateur tout en conservant les bons.
Des idées?
Edit Pour clarifier pourquoi j'utilise printf: j'ai une base de code relativement grande que je nettoie. Il utilise des wrappers printf pour faire des choses comme "écrire un avertissement, le consigner dans un fichier et éventuellement quitter le code avec une erreur". Je pourrais peut-être rassembler suffisamment de C ++ - foo pour le faire avec un wrapper cout, mais je préfère ne pas changer chaque appel warn () dans le programme juste pour me débarrasser de certains avertissements du compilateur.
"%l"
? Est-ce que ce ne sera pas toujours la bonne taille? Ou la portabilité est-elle importante?Réponses:
La plupart des compilateurs ont leur propre spécificateur
size_t
etptrdiff_t
arguments, Visual C ++ par exemple utilise respectivement% Iu et% Id, je pense que gcc vous permettra d'utiliser% zu et% zd.Vous pouvez créer une macro:
Usage:
la source
%z
prise en charge ou non dépend du runtime, pas du compilateur. L'utilisation__GNUC__
est donc un peu problématique, si vous mélangez GCC / mingw avec msvcrt (et sans utiliser le printf augmenté de mingw).Le
printf
spécificateur de format%zu
fonctionnera correctement sur les systèmes C ++; il n'est pas nécessaire de compliquer les choses.la source
C ++ 11
C ++ 11 importe C99 et
std::printf
doit donc prendre en charge le%zu
spécificateur de format C99 .C ++ 98
Sur la plupart des plates-formes,
size_t
etuintptr_t
sont équivalents, auquel cas vous pouvez utiliser laPRIuPTR
macro définie dans<cinttypes>
:Si vous voulez vraiment être en sécurité, lancez
uintmax_t
et utilisezPRIuMAX
:la source
Sur Windows et l'implémentation Visual Studio de printf
travaille pour moi. voir msdn
la source
VS 2008
aussi. Gardez également à l'esprit que l'on peut utiliser%Id
,%Ix
et%IX
aussi.Puisque vous utilisez C ++, pourquoi ne pas utiliser IOStreams? Cela devrait compiler sans avertissement et faire la bonne chose sensible au type, tant que vous n'utilisez pas une implémentation C ++ insensée qui ne définit pas un
operator <<
forsize_t
.Lorsque la sortie réelle doit être terminée
printf()
, vous pouvez toujours la combiner avec IOStreams pour obtenir un comportement de type sécurisé:Ce n'est pas très efficace, mais votre cas ci-dessus concerne les E / S de fichier, c'est donc votre goulot d'étranglement, pas ce code de formatage de chaîne.
la source
std::stringstream
place des flux IO.printf("x=%i, y=%i;\n", x, y);
vscout << "x=" << x << ", y=" << y << ";" << std::endl;
.voici une solution possible, mais ce n'est pas tout à fait jolie.
la source
La bibliothèque fmt fournit une implémentation portable (et sûre) rapide de l'
printf
inclusion duz
modificateur poursize_t
:En plus de cela, il prend en charge la syntaxe de chaîne de format de type Python et capture les informations de type afin que vous n'ayez pas à les fournir manuellement:
Il a été testé avec les principaux compilateurs et fournit une sortie cohérente sur toutes les plates-formes.
Avertissement : je suis l'auteur de cette bibliothèque.
la source
Le type effectif sous-jacent size_t dépend de l'implémentation . C Standard le définit comme le type renvoyé par l'opérateur sizeof; mis à part le fait d'être non signé et une sorte de type intégral, size_t peut être à peu près tout ce qui peut accueillir la plus grande valeur attendue d'être retournée par sizeof ().
Par conséquent, la chaîne de format à utiliser pour size_t peut varier en fonction du serveur. Il devrait toujours avoir le "u", mais peut être l ou d ou peut-être autre chose ...
Une astuce pourrait être de le convertir en le plus grand type intégral sur la machine, en garantissant aucune perte dans la conversion, puis en utilisant la chaîne de format associée à ce type connu.
la source
size_t
s sur le plus grand type intégral de la machine et d'utiliser la chaîne de format associée à ce type. Ma question est la suivante: y a-t-il un moyen de le faire tout en conservant un code propre (avertissements uniquement pour les erreurs de chaîne de format printf légitimes, pas de casts laids, etc.)? Je pourrais écrire un wrapper qui change la chaîne de format, mais GCC ne serait pas en mesure de me donner des avertissements lorsque j'ai légitimement gâché ma chaîne de format.Plus tard dans le code:
my::printf("test ", 1, '\t', 2.0);
la source