了解可变参数函数中的 va_list:gp_offset 增量、fp_offset 固定和垃圾值

问题描述 投票:0回答:1

在可变参数函数中,

va_list
类型通常被实现为结构体数组,其中每个数组元素都包含一个具有以下定义的结构体:

typedef struct {
   unsigned int gp_offset;
   unsigned int fp_offset;
   void *overflow_arg_area;
   void *reg_save_area;
} va_list[1];

在简单的代码片段中使用

va_list
时,我注意到有趣的行为:

#include <stdarg.h>
#include <stdio.h>

void example_function(int arg_count, ...) {
    va_list args;
    va_start(args, arg_count);

    int i = 0;
    while (i < arg_count) {
      printf("%d\n", va_arg(args, int));
      i++;
    }

    va_end(args);
}

int main() {
    example_function(3, 1, 2, 3);
    return 0;
}

在此代码中:

  1. gp_offset
    从 8 开始,并在 while 循环中每次调用 va_arg 时递增 8。
  2. fp_offset
    保持固定为 48。
  3. overflow_arg_area
    reg_save_area
    使用垃圾值进行初始化。

我想了解:

  • 为什么每次调用
    gp_offset
    va_arg
    都会增加 8?
  • 为什么
    fp_offset
    固定为48?
  • 为什么
    overflow_arg_area
    reg_save_area
    指向垃圾值?
c variadic-functions
1个回答
0
投票
  • gp_offset
    增加 8,因为参数保存在通用寄存器中。 在调用带参数的函数之前,前 6 个参数将首先移至寄存器,其余参数移至堆栈(这取决于您的机器、操作系统...),然后调用该函数。每个寄存器有 8 个字节。
  • fp_offset
    是一个浮点偏移量,当 va_arg 返回的当前参数是 double 或 float 类型时,它会被更新。

double 和 float 有专门的寄存器,如果我记得的话,它们每个的大小都是 16 个字节。

© www.soinside.com 2019 - 2024. All rights reserved.