C堆栈内存转储,为什么第一个参数出现两次?

标签 c stack arguments variadic-functions

我在 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 的实现?极度依赖编译器?

最佳答案

直接查看汇编程序将是解决此问题的更好方法,但我认为两次看到 42 的原因是 st 编译器实现堆栈的方式的人工制品。大多数情况下,堆栈从内存中的高位开始并向下增长。因此,您的函数会将参数存储在 main 函数框架下方的堆栈框架中。然后从第一个参数的地址向上打印。所以你得到第一个参数,然后是堆栈帧的开始,然后是一些主堆栈帧,其中将包括传递给你的函数的参数。这就是为什么你两次看到 42 的原因。 当然,这一论点假设编译器和操作系统以某种方式工作。正如我已经说过的,查看程序集会给你一个更准确的画面。

关于C堆栈内存转储,为什么第一个参数出现两次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20587410/

相关文章:

c - C语言中的隐式声明

c - 当我使用 malloc 函数时,我不断收到错误

c++ - 使用堆栈将字符串格式的小数转换为 double

当未提供函数的参数但用于对向量进行子集化时,R 不会报告错误

java - KSH 使用变量中的参数运行 Java

clojure - 匿名函数在clojure中需要多少个参数?

c - 如何用C写一个DLL文件?

c - 在c中执行时正则表达式不起作用

android - 随着最近的应用程序切换,从通知开始/恢复任务返回堆栈

c++ - 使用 strlen() 在堆栈中分配缓冲区