以下代码按预期工作GCC https://godbolt.org/z/bbcdfj and Clang https://godbolt.org/z/WPc79z,但是,我相信它包含未定义的行为。它起作用的可能原因是省略号中的参数在堆栈中以 64 位大小的块传递,即使提取了 32 位大小的值也是如此。
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
void foo(int count, ...) {
va_list args;
va_start(args, count);
for (int i = 0; i < count; i++) {
uint32_t x = va_arg(args, uint32_t);
printf("%"PRIu32" ", x);
}
printf("\n");
va_end(args);
}
void bar(int count, ...) {
va_list args;
va_start(args, count);
for (int i = 0; i < count; i++) {
uint64_t x = va_arg(args, uint64_t);
printf("%"PRIu64" ", x);
}
printf("\n");
va_end(args);
}
int main() {
uint32_t a = 1, b = (uint32_t)10000000000, c = (uint32_t)-1;
uint64_t x = 1, y = 10000000000, z = (uint64_t)-1;
foo(3, a, b, c);
foo(3, x, y, z); // UB
bar(3, a, b, c); // UB
bar(3, x, y, z);
}
Output:
1 1410065408 4294967295 // ok
1 1410065408 4294967295 // ok
1 1410065408 4294967295 // ok
1 10000000000 18446744073709551615 // ok
如果某些架构使用 32 位偏移量来实现函数中的堆栈foo
,那么当传递 64 位值时,其结果将不正确。在这种情况下,输出可能如下所示:
1 1410065408 4294967295 // ok
1 0 1410065408 // incorrect
6056184812580896769 12884901887 18446744073709551615 // incorrect
1 10000000000 18446744073709551615 // ok
如何正确实现单个函数而不是两个函数foo
and bar
并能够使用 32 位和 64 位参数调用它?