Wenn in c eine Variable-Argument-Funktion aufgerufen wird, werden die Integer-Parameter auf int hochgestuft, und Gleitkomma-Parameter werden auf double
hochgestuftDa der Prototyp keine Typen für optionale Argumente angibt, werden bei einem Aufruf einer variadischen Funktion die Standardargument-Aktionen für die optionalen Argumentwerte ausgeführt. Dies bedeutet, dass die Objekte vom Typ
char
odershort int
(ob signiert oder nicht) entweder aufint
oderunsigned int
heraufgestuft werden; und dass Objekte vom Typfloat
zum Typdouble
hochgestuft werden. Wenn der Aufrufer also einchar
als optionales Argument übergibt, wird es in einint
hochgestuft, und die Funktion kann mitva_arg (ap, int)
darauf zugreifen.
int
Typ sollte 4 Byte auf 32-Bit-Maschinen und 8 Byte auf 64-Bit-Maschinen sein, ist das richtig?
Also frage ich mich was anhängen wenn ich ein long long int
an eine Variable Argument Funktion wie printf mit %lld
format weitergebe.
Und noch einmal, ich frage mich, was anhängen, wenn ich eine long double
Variable an printf mit %Lf
Format übergeben (egal ob auf 32 oder 64 Bit Maschinen).
[ Bearbeitet ]
auf einer 32-Bit-Maschine, habe ich Folgendes versucht:
%Vor%Das Ergebnis ist:
%Vor% Das lässt mich denken, dass nicht alle Parameter zu int
befördert werden, sonst würde ich anstelle von 8589934592 den Wert 0 erhalten.
Vielleicht werden nur Argumente, die kleiner als int
sind, in int
hochgestuft. Und etwas ähnliches könnte für Gleitkommatypen sein.
[ Bearbeitet ]
auf einer 64-Bit-Maschine führe ich das aus:
%Vor%und hole
%Vor% Wenn ich den Standard gut verstehe, werden nur char
und short
zu int
hochgestuft. Ich frage mich, was in kleineren Architekturen, wie 16-Bit oder 8-Bit-MCU passieren. Ich denke, dass int
size ist abhängig von der Architektur, aber ich frage mich, ob sizeof(int)
1 auf 8-Bit-Architektur sein kann. In diesem Fall könnte die Beförderung von short
zu int
unmöglich sein, wenn nicht einige Bits verloren gehen
" int
type sollte 4 Byte auf 32 Bit Maschinen und 8 Byte auf 64 Bit Maschinen sein, richtig?" Nein. Gemäß dem Standard muss int
s mindestens
Wenn Sie ein long long int
an printf()
übergeben, unterliegt es nicht dem ganzzahlige Werbeaktionen (§6.3.1.1 2) :
Das Folgende kann in einem Ausdruck verwendet werden, wo immer ein int oder unsigned ist int kann verwendet werden:
- Ein Objekt oder Ausdruck mit einem Integer-Typ (anders als int oder unsigned int), dessen Integer-Conversion-Rang kleiner oder gleich ist der Rang von int und unsigned int.
- Ein Bitfeld vom Typ _Bool, int, signed int oder unsigned int.
Wenn ein int alle Werte des Originaltyps darstellen kann (als eingeschränkt durch die Breite für ein Bitfeld) wird der Wert in ein int umgewandelt; Andernfalls wird es in einen unsigned int konvertiert. Diese heißen die Ganzzahlspromotions.58) Alle anderen Typen werden durch die ganze Zahl unverändert Werbeaktionen .
Wenn Sie ein long double
an printf()
übergeben, wird keine Umwandlung vorgenommen (§ 6.5.2.2 6) :
Wenn der Ausdruck, der die aufgerufene Funktion bezeichnet, einen Typ hat, der enthält keinen Prototyp, an dem Ganzzahl-Promotions ausgeführt werden Jedes Argument und alle Argumente, die den Typ float haben, werden in promoted doppelt. Diese werden als Standard-Argument-Promotions bezeichnet.
Die Konvertierungsbezeichner, die den Argumenten in der printf()
-Anweisung entsprechen, haben keinen Einfluss auf diese Promotions und Conversions, außer es wird undefiniertes Verhalten geben, wenn die Spezifizierer und die Typen ihrer entsprechenden Argumente nicht übereinstimmen.
Also werden die Integer-Promotions durchgeführt und float
s werden in double
s konvertiert, aber " Implizit werden keine weiteren Konvertierungen durchgeführt "(§6.5.2.2 8) .
Adressieren Sie Ihre Bearbeitung auf die Frage: "Das lässt mich denken, dass nicht alle Parameter zu int
befördert werden." Richtig. Nur Integer-Typen mit ganzzahligen Conversion-Rang "kleiner als oder gleich dem Rang von int
und unsigned int
" unterliegen einer ganzzahligen Heraufstufung. Es ist einfacher für Fließkommatypen; float
s werden zu double
hochgestuft. Das ist alles.
Es lohnt sich, darauf hinzuweisen, dass nach §6.2.5 10 gibt es drei echte Gleitkommaarten, float
, double
und long double
. Die Werte, die von float
gehalten werden können, sind eine Teilmenge der Werte, die von double
gehalten werden können, die wiederum eine Teilmenge der Werte sind, die von long double
gehalten werden können. Daher gibt es keine Möglichkeit der Förderung für long double
-Typen.
Außerdem, §6.3.1.1 1 :
Der Rang von long long int soll größer sein als der von long int, was größer sein soll als der Rang von int, der größer sein soll als der Rang von short int, der größer sein soll als der Rang von signiertes Zeichen.
Es besteht also keine Möglichkeit, dass long long int
oder long int
jemals in int
oder unsigned int
hochgestuft werden.
Was Ihr letztes Anliegen betrifft, dass die Beförderung von short
zu int
in einigen Implementierungen unmöglich sein kann, ohne einige Bits zu verlieren, beachten Sie, dass §6.2.5 8 garantiert, dass ein int
einen short
enthalten kann, da der Conversion-Rang eines int
sein muss größer als die von short
:
Für zwei beliebige Integer-Typen mit derselben Signedness und anderen ganzzahliger Umrechnungsrang (siehe 6.3.1.1), der Wertebereich des Typs mit kleineren Integer-Konvertierungsrang ist ein Teilbereich der Werte von der andere Typ.
int Typ sollte 4 Byte auf 32 Bit Maschinen und 8 Byte auf 64 Bit Maschinen sein, stimmt das?
Wahrscheinlich nicht. Zuallererst macht C keine Garantien über die Größe von int
, abgesehen davon, dass es muss mindestens 2 Bytes sein muss (in der Lage, mindestens den Wert 2 ^ 16/2 - 1 = zu halten 32767). Nichts in C verhindert int
von 8 Bytes, aber das ist nicht sehr praktisch.
Die Konvention lautet: Alle 8- und 16-Bit-Computer verwenden 16 Bit int
. Alle anderen Computer verwenden 32 Bit int
. Dies ist ein Industriestandard. Jede Abweichung von dieser Konvention wäre sehr exotisch, obwohl theoretisch von C. erlaubt.
Ich frage mich also, was anhängen, wenn ich einen langen langen int an eine Variable Argument-Funktion wie printf mit% lld-Format übergeben.
Du bekommst einen langen langen int. Es findet keine Promotion statt, da die Variable nicht zu den genannten kleinen Typen gehört. Der verwendete Formatbezeichner ist für die Werberegeln irrelevant.
Das lässt mich denken, dass nicht alle Parameter zu int hochgestuft werden
Tatsächlich. Nur die Typen, die der Standard erwähnt, werden gefördert. Die formale Definition der Default-Argument-Promotions finden Sie in C11 6.5.2.2/6:
... die Integer-Promotions werden für jedes Argument ausgeführt und Argumente mit dem Typ float werden zu double hochgestuft. Diese sind die Standard-Argument-Promotions genannt.
Dies bedeutet, dass nur die kleinen Integer-Typen (siehe die Integer-Promotion-Regel) und float
hochgestuft werden. Keine anderen Arten.
Warum Sie denken, dass Ihre Beispiele, die verschiedene Schriftgrößen drucken, irgendeine Relevanz in Bezug auf die Standard-Argument-Promotion haben, habe ich keine Ahnung.
Ich frage mich also, was anhängen, wenn ich eine
long long int
an eine Variable übergebe Argument funktioniert wie printf mit%lld
format. Und wieder frage ich mich was angehängt wird, wenn ich eine Variablelong double
an printf mit%Lf
übergebe Format (egal ob auf 32 oder 64 Bit Maschinen).
Es passiert nichts, da long long int
mindestens die gleiche Größe wie int
haben muss. Selbst im "pesimistischsten" Szenario, in dem sizeof(long long int) == sizeof(int)
steht, wird das Argument unverändert übergeben (ohne Werbung). Gleiches gilt für long double
.
Tags und Links c c99 floating-point printf int