Ich habe einen C ++ - Code, der Folgendes druckt size_t
:
size_t a;
printf("%lu", a);
Ich möchte, dass dies ohne Warnungen auf 32- und 64-Bit-Architekturen kompiliert wird.
Wenn dies C99 wäre, könnte ich verwenden printf("%z", a);
. AFAICT %z
existiert jedoch in keinem Standard-C ++ - Dialekt. Also muss ich stattdessen tun
printf("%lu", (unsigned long) a);
Das ist wirklich hässlich.
Wenn es keine Möglichkeit gibt, size_t
s in die Sprache zu drucken , frage ich mich, ob es möglich ist, einen printf-Wrapper oder einen solchen zu schreiben, der die entsprechenden Casts auf size_t
s einfügt , um falsche Compiler-Warnungen zu beseitigen und gleichzeitig die guten beizubehalten.
Irgendwelche Ideen?
Bearbeiten Um zu verdeutlichen, warum ich printf verwende: Ich habe eine relativ große Codebasis, die ich bereinige. Es verwendet printf-Wrapper, um beispielsweise eine Warnung zu schreiben, sie in einer Datei zu protokollieren und den Code möglicherweise mit einem Fehler zu beenden. Möglicherweise kann ich genug C ++ - foo aufbringen, um dies mit einem Cout-Wrapper zu tun, aber ich möchte lieber nicht jeden warn () -Aufruf im Programm ändern, nur um einige Compiler-Warnungen zu entfernen.
"%l"
? Wird das nicht immer die richtige Größe sein? Oder spielt Portabilität eine Rolle?Antworten:
Die meisten Compiler haben einen eigenen Bezeichner für
size_t
undptrdiff_t
Argumente. Visual C ++ verwendet beispielsweise% Iu bzw.% Id. Ich denke, dass Sie mit gcc% zu und% zd verwenden können.Sie könnten ein Makro erstellen:
Verwendung:
quelle
%z
unterstützt wird oder nicht, hängt von der Laufzeit ab, nicht vom Compiler. Die Verwendung__GNUC__
ist daher ein kleines Problem, wenn Sie GCC / mingw mit msvcrt mischen (und ohne das erweiterte printf von mingw zu verwenden).Der
printf
Formatbezeichner%zu
funktioniert auf C ++ - Systemen einwandfrei. Es besteht keine Notwendigkeit, es komplizierter zu machen.quelle
C ++ 11
C ++ 11 importiert C99 und
std::printf
sollte daher den C99-%zu
Formatbezeichner unterstützen.C ++ 98
Auf den meisten Plattformen
size_t
unduintptr_t
gleichwertig sind, in diesem Fall können Sie die verwenden können ,PRIuPTR
Makro definiert in<cinttypes>
:Wenn Sie wirklich sicher sein wollen, werfen Sie auf
uintmax_t
und verwenden SiePRIuMAX
:quelle
Unter Windows und der Visual Studio-Implementierung von printf
funktioniert bei mir. siehe msdn
quelle
VS 2008
. Denken Sie auch daran, dass man verwenden kann%Id
,%Ix
und%IX
auch.Warum nicht IOStreams verwenden, da Sie C ++ verwenden? Das sollte ohne Warnungen kompiliert werden und die richtige typbewusste Aktion ausführen, solange Sie keine hirntote C ++ - Implementierung verwenden, die kein
operator <<
for definiertsize_t
.Wenn die eigentliche Ausgabe erledigt werden muss
printf()
, können Sie sie dennoch mit IOStreams kombinieren, um ein typsicheres Verhalten zu erzielen:Es ist nicht sehr effizient, aber Ihr obiger Fall befasst sich mit Datei-E / A. Das ist also Ihr Engpass, nicht dieser Code zur Formatierung von Zeichenfolgen.
quelle
std::stringstream
anstelle von IO-Streams.printf("x=%i, y=%i;\n", x, y);
vscout << "x=" << x << ", y=" << y << ";" << std::endl;
.Hier ist eine mögliche Lösung, aber es ist keine schöne.
quelle
Die fmt - Bibliothek bietet eine schnelle portable (und sicher) Umsetzung
printf
einschließlich derz
Modifikator fürsize_t
:Darüber hinaus unterstützt es die Python-ähnliche Format-String-Syntax und erfasst Typinformationen, sodass Sie diese nicht manuell bereitstellen müssen:
Es wurde mit großen Compilern getestet und bietet plattformübergreifende konsistente Ausgabe.
Haftungsausschluss : Ich bin der Autor dieser Bibliothek.
quelle
Der effektive Typ, der size_t zugrunde liegt, ist implementierungsabhängig . C Standard definiert es als den Typ, der vom Operator sizeof zurückgegeben wird. Abgesehen davon, dass es nicht signiert ist und eine Art integraler Typ ist, kann size_t so ziemlich alles sein, welche Größe den größten Wert aufnehmen kann, der von sizeof () erwartet wird.
Folglich kann die für eine size_t zu verwendende Formatzeichenfolge je nach Server variieren. Es sollte immer das "u" haben, kann aber l oder d oder vielleicht etwas anderes sein ...
Ein Trick könnte darin bestehen, ihn in den größten integralen Typ auf dem Computer umzuwandeln, um sicherzustellen, dass bei der Konvertierung kein Verlust auftritt, und dann die diesem bekannten Typ zugeordnete Formatzeichenfolge zu verwenden.
quelle
size_t
s auf den größten integralen Typ auf der Maschine gießen und die diesem Typ zugeordnete Formatzeichenfolge verwenden würde. Meine Frage lautet: Gibt es eine Möglichkeit, dies zu tun, während sauberer Code beibehalten wird (Warnungen nur für legitime Fehler im String-Format im Printf-Format, keine hässlichen Casts usw.)? Ich könnte einen Wrapper schreiben, der die Formatzeichenfolge ändert, aber dann kann GCC mich nicht warnen, wenn ich meine Formatzeichenfolge rechtmäßig durcheinander gebracht habe.Später im Code:
my::printf("test ", 1, '\t', 2.0);
quelle