我正在用C语言试验堆栈的地址空间,发现了让我抬起眉毛的东西。以下代码片段调用一个函数,该函数依次打印出以第一个参数的地址开头的内存的整数值。
#include <stdio.h>
#include <stdarg.h>
void func(int arg, int second, ...) {
int i=0;
for (; i < 20; i++) {
int* addr = &arg + i;
printf("* %d\n", *addr);
}
}
int main() {
func(42, 67, 24, 92);
return 0;
}
输出是这样的:
* 42 <
* 1075105048
* -1081967932
* 1073841448
* -16121856
* 1075105060
* 1073828160
* -1081967880
* 134513921
* 42 <
* 67 <
* 24 <
* 92 <
* 134513984
* 0
* -1081967880
* 134513529
* -16121856
* -1081967856
* -1081967816
现在,让我怀疑的是我标有<
标志的线条。一行中的四个元素等于我传递给函数的参数。但为什么值第一个参数在输出中出现两次?
传递给C函数的参数是否有标准化的内存布局,或者stdarg.h
的实现是否依赖于编译器?
答案 0 :(得分:1)
直接查看汇编程序是一种更好的解决方法,但我认为两次看到42的原因是st编译器实现堆栈的方式的假象。堆栈大部分从内存中的高位开始并逐渐减少。因此,您的函数将把参数存储在main函数的框架下方的堆栈框架中。然后,您可以从第一个参数的地址向上打印。所以你得到第一个参数,然后是堆栈帧的开始,接着是一些主堆栈帧,它将包含传递给你的函数的参数。这就是为什么你看到42次两次。 当然,这一论点假设编译器和操作系统以某种方式工作。正如我已经说过的那样,看着这个装配会给你一个更加准确的画面。