2013-03-30 5 views
8

Warum viele Online-Juroren raten: "Verwenden Sie nicht den% lld-Spezifizierer zum Lesen oder Schreiben von 64-Bit-Ganzzahlen in C++. Es wird bevorzugt, die cin, cout-Streams oder den% I64d-Spezifizierer zu verwenden." ?Warum wird die Verwendung von cin, cout oder% I64d gegenüber% lld in C++ bevorzugt?

+6

Weil Sie nicht sicher sein können, dass "long long" 64 Bit lang ist, zum Beispiel? –

+1

Weil 'printf' nicht typsicher ist. Wenn Benutzer einen anderen Typ übergeben, erhalten Sie ein nicht definiertes Verhalten.Während bei 'cout' der Compiler je nach Typ eine gültige Überladungsversion wählt oder einen Fehler zurückgibt, gibt es kein Undefined-Verhalten. –

+0

(Weil die Verwendung von C++ nicht hirngeschützt ist ...) –

Antwort

8

Ich glaube, die Antwort bezieht sich auf %lld bedeutet long long decimal, die nicht garantiert wird, 64-Bit zu sein. Es könnte beispielsweise 128 Bit auf einigen Systemen sein. (Obwohl, wenn die Variable long long eher als, sagen wir, uint64_t, dann erwarte ich %lld ist das Richtige zu verwenden - oder wäre es umgekehrt schief gehen)

Leider das Design von printf und scanf und ihre Geschwister ist so, dass die Compiler-Implementierung und das Format übereinstimmen müssen.

Offensichtlich sind cout und cin sicher in dem Sinne, dass der Compiler die richtige Ausgabe und Eingabe in sich selbst auswählen wird.

Es kann auch etwas damit zu tun, was Compiler die "Online-Richter" verwenden - ich denke, Microsoft Compiler unterstützt 64-Bit-Ganzzahlen, aber nicht long long, und somit nicht %lld, aber hatte %l64d.

+0

Ich stieß auf diesen Link http://codeforces.com/blog/entry/417#, der sagt: Wenn Sie unter "GNU C++" oder "GNU C" -Option senden, verwenden Sie diese: printf ("% I64d \ n" , n); aber nicht das: printf ("% lld \ n", n); Wenn Sie unter "MS C++" -Option senden, sollten beide Varianten funktionieren. – rishabh

+0

Ich vermute, das liegt daran, dass GNU C tatsächlich eine ältere MS VC-Laufzeitbibliothek verwendet (da glibc für Windows nicht ohne weiteres verfügbar ist). –

4

Die << und >> Operatoren auf cin und cout haben Versionen für jede Integer- und Fließkommatyp. Wenn Sie cin und cout verwenden, tun Sie einfach cin >> integer_variable oder cout << integer_variable und Sie sind fertig, cin und cout werden herausfinden, was zu tun ist.

Wenn Sie irgendeine Art von printf() verwenden, dann müssen Sie sehr vorsichtig sein, was Sie zu ihm übergeben. Wenn Sie es ein int geben, müssen Sie auch seine Typspezifizierer "%d", übergeben für unsigned int es "%u" ist, für long es "%ld" ist, für unsigned long long es "%llu" ist, für size_t es ist "%zu" und so weiter. Wenn Sie einen Typspezifizierer übergeben, der nicht mit dem Typ Ihrer Ganzzahl übereinstimmt, rufen Sie undefiniertes Verhalten auf. Infolgedessen kann Ihr Programm falsche Zahlen drucken oder sich selbst korrumpieren oder hängen oder abstürzen oder sich auf eine andere geheimnisvolle Weise schlecht benehmen.

Jetzt hat der C++ 11-Sprachenstandard (und C99) mindestens einen Integer-Typ, der 64-Bit oder länger ist, long long (und sein unsigniertes Gegenstück, unsigned long long). Wenn Sie es verwenden, müssen Sie beachten, dass es länger als 64 Bits sein kann. Wenn Ihr Compiler einen anderen Typ bereitstellt, __int64 oder int64_t (plus die unsignierte Version desselben), das ist genau 64-Bit, sollten Sie ihre Typspezifizierer nicht mischen und abgleichen, da dies oft fälschlicherweise geschieht. Sie sollten immer noch "%lld" und "%llu" für long long und unsigned long long und was auch immer für __int64 (vielleicht, "%I64d") und für int64_t (PRId64 Makro).

Grundsätzlich sollten Sie entweder vermeiden printf()-like Funktionen oder mit ihnen sehr vorsichtig sein.

Verwandte Themen