Gemäß this answer werden numerische Konstanten, die an variadische Funktionen übergeben werden, immer als int
behandelt, wenn sie in eins passen. Das lässt mich fragen, warum der folgende Code mit beiden funktioniert: int
und long long
. Betrachten Sie die folgende Funktionsaufruf:Warum funktioniert meine variadische Funktion sowohl mit int als auch mit long long?
testfunc(4, 1000, 1001, 1002, 1003);
testfunc
sieht wie folgt aus:
void testfunc(int n, ...)
{
int k;
va_list marker;
va_start(marker, n);
for(k = 0; k < n; k++) {
int x = va_arg(marker, int);
printf("%d\n", x);
}
va_end(marker);
}
Dies funktioniert gut. Er druckt 1000, 1001, 1002, 1003. Aber zu meiner Überraschung, der folgende Code funktioniert auch:
void testfunc(int n, ...)
{
int k;
va_list marker;
va_start(marker, n);
for(k = 0; k < n; k++) {
long long x = va_arg(marker, long long);
printf("%lld\n", x);
}
va_end(marker);
}
Warum ist das so? Warum funktioniert es auch mit long long
? Ich dachte, dass numerische Integer-Konstanten als int
übergeben wurden, wenn sie in einem passen? (siehe Link oben) Wie kann es also sein, dass es auch mit long long
funktioniert?
Verdammt, es funktioniert sogar, wenn man zwischen int
und long long
wechselt. Dies ist verwirrend, das Heck aus mir:
void testfunc(int n, ...)
{
int k;
va_list marker;
va_start(marker, n);
for(k = 0; k < n; k++) {
if(k & 1) {
long long x = va_arg(marker, long long);
printf("B: %lld\n", x);
} else {
int x = va_arg(marker, int);
printf("A: %d\n", x);
}
}
va_end(marker);
}
Wie kann das sein? Ich dachte alle meine Parameter wurden als int
übergeben ... Warum kann ich beliebig zwischen int
und long long
beliebig hin und her wechseln? Ich bin jetzt wirklich verwirrt ...
Danke für jedes Licht vergossen auf diese!
Welchen Chip verwenden Sie? Was ist das ABI (Application Binary Interface) dafür? Sie können damit davonkommen, weil Sie sich auf einem 64-Bit-Rechner befinden und die ersten N Argumente der Variadic-Argumente in Registern übertragen werden, die 64-Bit-Register sind, groß genug für 'long long'. Versuchen Sie, die Funktion mit 20 Argumenten - oder mehr als 32 Argumenten - aufzurufen. Die Idee ist, dass, wenn es zu viele Argumente gibt, um in die Register zu passen, die Extras als "int" auf dem Stapel übergeben werden. –
Ich bin auf 64-Bit-Ubuntu mit gcc. – Andreas
Undefiniertes Verhalten umfasst Verhalten, das zufällig funktioniert. Es wird sicherlich auf einem 64-Bit-Intel-Prozessor, der ABI fordert 8 Bytes pro Argument und die oberen 32-Bits werden immer Null und der Prozessor ist Little-Endian. Tinker mit diesen zufälligen Eigenschaften und Sie werden einen Unfall haben. –