当前位置: 代码迷 >> 综合 >> C语言函数参数数量不同、参数为变参时参数的传递规则
  详细解决方案

C语言函数参数数量不同、参数为变参时参数的传递规则

热度:51   发布时间:2024-02-23 15:42:42.0

写这篇笔记是因为对C语言函数参数的传递突然有了很多疑惑。ATPCS规定R0~R4用于存储前四个参数,那么如果对前四个参数取址得到的是什么结果呢?CPU的寄存器是自有的,不在内存空间中。如果要实现变参函数,找不到参数的入口地址,那接下来的工作就无法完成。于是写了一些代码,做了一些实验来寻找答案。代码在ARM和MSP430芯片上通过运行。

结论

   (1) 参数数量固定, 并且参数数量小于等于4个.

      参数会从左到右传到R0~R3寄存器中, 同时在内存中会有这些参数的副本, 并且参数按从左到右依次占据内存从高地址到低地址的连续空间.

   (2) 参数数量固定, 并且参数数量大于等于5个

      前四个参数的行为同(1), 从第5个参数到后面所有参数, 按从左到右依次占据内存从低址到高地址的连续空间.

   (3) 参数数量不固定

      原则: 最后一个固定参数的相邻高地址空间开始存放变参, 并且变参按从左到右依次占据内从从低地址到高地址的连续空间.

      对于其余固定参数, 优先传到R0~R3, 而内存中也会存有这些参数的副本, 从高地址到低地址连续存储; 当R0~R3不够用时, 继续将参数从低地址到高地址存储到内存中, 直到和最后一个固定参数相邻.

 

   P.S. 在函数中获取参数的地址, 得到的是其在内存中的地址, 对于需要传进R0~R3的参数, 则是其在内存中副本的地址.

 

实验

(一) 使用arm-linux-gnueabihf-gcc编译, 在imx6ull上运行. IMX6ULL是32位单片机, int类型数据占4个字节, 指针类型占4个字节.

 

#include "stdio.h"
int func_va_list(int a, int b, int c, int d, int e, int f, ...){int *p;p = (int*)&a;printf("&a = 0x%8x, p= 0x%8x, p_a = %d, a = %d\n", &a, p, *p, a);p--;printf("p--\n");printf("&b = 0x%8x, p= 0x%8x, p_b = %d, b = %d\n", &b, p, *p, b);p--;printf("&c = 0x%8x, p= 0x%8x, p_c = %d, c = %d\n", &c, p, *p, c);p--;printf("&d = 0x%8x, p= 0x%8x, p_d = %d, d = %d\n", &d, p, *p, d);p--;printf("&e = 0x%8x, p= 0x%8x, p_e = %d, e = %d\n", &e, p, *p, e);p--;printf("&f = 0x%8x, p= 0x%8x, p_f = %d, f = %d\n", &f, p, *p, f);p--;printf("p= 0x%8x, p_g = %d\n", p, *p);return a+f;
}int func_va_list2(int a, ...){int *p;p = (int*)&a;printf("p= 0x%8x, p_a = %d\n", p, *p);p++;printf("p++\n");printf("p= 0x%8x, p_b = %d\n", p, *p);p++;printf("p= 0x%8x, p_c = %d\n", p, *p);p++;printf("p= 0x%8x, p_d = %d\n", p, *p);p++;printf("p= 0x%8x, p_e = %d\n", p, *p);p++;printf("p= 0x%8x, p_f = %d\n", p, *p);p++;printf("p= 0x%8x, p_g = %d\n", p, *p);return a+(*p);}int func_va_list3(int a, int b, ...){int *p;p = (int*)&a;printf("p= 0x%8x, p_a = %d, &a = 0x%8x\n", p, *p, &a);p++;printf("p++\n");printf("p= 0x%8x, p_b = %d, &b = 0x%8x\n", p, *p, &b);p++;printf("p= 0x%8x, p_c = %d\n", p, *p);p++;printf("p= 0x%8x, p_d = %d\n", p, *p);p++;printf("p= 0x%8x, p_e = %d\n", p, *p);p++;printf("p= 0x%8x, p_f = %d\n", p, *p);p++;printf("p= 0x%8x, p_g = %d\n", p, *p);return a+(*p);}int func_va_list4(int a, int b, ...){int *p;p = (int*)&a;printf("p= 0x%8x, p_a = %d, &a = 0x%8x\n", p, *p, &a);p = (int *)&b;printf("p = (int *)&b;\n");printf("p= 0x%8x, p_b = %d, &b = 0x%8x\n", p, *p, &b);p++;printf("p= 0x%8x, p_c = %d\n", p, *p);p++;printf("p= 0x%8x, p_d = %d\n", p, *p);p++;printf("p= 0x%8x, p_e = %d\n", p, *p);p++;printf("p= 0x%8x, p_f = %d\n", p, *p);p++;printf("p= 0x%8x, p_g = %d\n", p, *p);return a+(*p);}int func_va_list5(int a, int b, int c, int d, int e, int f, int g){int *p;p = (int*)&a;printf("&a = 0x%8x, p= 0x%8x, p_a = %d, a = %d\n", &a, p, *p, a);p--;printf("p--\n");printf("&b = 0x%8x, p= 0x%8x, p_b = %d, b = %d\n", &b, p, *p, b);p--;printf("&c = 0x%8x, p= 0x%8x, p_c = %d, c = %d\n", &c, p, *p, c);p--;printf("&d = 0x%8x, p= 0x%8x, p_d = %d, d = %d\n", &d, p, *p, d);p--;printf("&e = 0x%8x, p= 0x%8x, p_e = %d, e = %d\n", &e, p, *p, e);p--;printf("&f = 0x%8x, p= 0x%8x, p_f = %d, f = %d\n", &f, p, *p, f);p--;printf("&g = 0x%8x, p= 0x%8x, p_g = %d, g = %d\n", &g, p, *p, g);return a+f;
}int main(void){printf("------------------------------------func_va_list(int a, int b, int c, int d, int e, int f, ...)\n");func_va_list(1, 2, 3, 4, 5, 6, 7);printf("------------------------------------func_va_list2(int a, ...)\n");func_va_list2(1, 2, 3, 4, 5, 6, 7);printf("------------------------------------func_va_list3(int a, int b, ...)\n");func_va_list3(1, 2, 3, 4, 5, 6, 7);printf("------------------------------------func_va_list4(int a, int b, ...)\n");func_va_list4(1, 2, 3, 4, 5, 6, 7);printf("------------------------------------func_va_list5(int a, int b, int c, int d, int e, int f, int g)\n");func_va_list5(1, 2, 3, 4, 5, 6, 7);return 0;
}

实验结果

------------------------------------func_va_list(int a, int b, int c, int d, int e, int f, ...)
&a = 0x7ee89c44, p= 0x7ee89c44, p_a = 1, a = 1
p--
&b = 0x7ee89c40, p= 0x7ee89c40, p_b = 2, b = 2
&c = 0x7ee89c3c, p= 0x7ee89c3c, p_c = 3, c = 3
&d = 0x7ee89c38, p= 0x7ee89c38, p_d = 4, d = 4
&e = 0x7ee89c58, p= 0x7ee89c34, p_e = 1995486037, e = 5
&f = 0x7ee89c5c, p= 0x7ee89c30, p_f = 5, f = 6
p= 0x7ee89c2c, p_g = 5
------------------------------------func_va_list2(int a, ...)
p= 0x7ee89c48, p_a = 1
p++
p= 0x7ee89c4c, p_b = 2
p= 0x7ee89c50, p_c = 3
p= 0x7ee89c54, p_d = 4
p= 0x7ee89c58, p_e = 5
p= 0x7ee89c5c, p_f = 6
p= 0x7ee89c60, p_g = 7
------------------------------------func_va_list3(int a, int b, ...)
p= 0x7ee89c34, p_a = 1, &a = 0x7ee89c34
p++
p= 0x7ee89c38, p_b = 4, &b = 0x7ee89c4c
p= 0x7ee89c3c, p_c = 2129173564
p= 0x7ee89c40, p_d = 2129173608
p= 0x7ee89c44, p_e = 2129173608
p= 0x7ee89c48, p_f = 67891
p= 0x7ee89c4c, p_g = 2
------------------------------------func_va_list4(int a, int b, ...)
p= 0x7ee89c34, p_a = 1, &a = 0x7ee89c34
p = (int *)&b;
p= 0x7ee89c4c, p_b = 2, &b = 0x7ee89c4c
p= 0x7ee89c50, p_c = 3
p= 0x7ee89c54, p_d = 4
p= 0x7ee89c58, p_e = 5
p= 0x7ee89c5c, p_f = 6
p= 0x7ee89c60, p_g = 7
------------------------------------func_va_list5(int a, int b, int c, int d, int e, int f, int g)
&a = 0x7ee89c44, p= 0x7ee89c44, p_a = 1, a = 1
p--
&b = 0x7ee89c40, p= 0x7ee89c40, p_b = 2, b = 2
&c = 0x7ee89c3c, p= 0x7ee89c3c, p_c = 3, c = 3
&d = 0x7ee89c38, p= 0x7ee89c38, p_d = 4, d = 4
&e = 0x7ee89c58, p= 0x7ee89c34, p_e = 1995486037, e = 5
&f = 0x7ee89c5c, p= 0x7ee89c30, p_f = 5, f = 6
&g = 0x7ee89c60, p= 0x7ee89c2c, p_g = 5, g = 7

(二)使用TI的MSP430编译器, 开发环境CCS, 运行环境MSP430FR5994. MSP430是16位单片机, int类型数据占2个字节, 指针类型占4个字节.

int func_va_list(volatile int a, volatile int b, volatile int c, volatile int d, volatile int e, volatile int f, ...){volatile int *p;p = (int*)&a;DBG_PRINTF("&a = 0x%08X, p= 0x%08X, p_a = %d, a = %d\r\n", &a, p, *p, a);p--;DBG_PRINTF("p--;\r\n");DBG_PRINTF("&b = 0x%08X, p= 0x%08X, p_b = %d, b = %d\r\n", &b, p, *p, b);p--;DBG_PRINTF("&c = 0x%08X, p= 0x%08X, p_c = %d, c = %d\r\n", &c, p, *p, c);p--;DBG_PRINTF("&d = 0x%08X, p= 0x%08X, p_d = %d, d = %d\r\n", &e, p, *p, d);p--;DBG_PRINTF("&e = 0x%08X, p= 0x%08X, p_e = %d, e = %d\r\n", &e, p, *p, e);p--;DBG_PRINTF("&f = 0x%08X, p= 0x%08X, p_f = %d, f = %d\r\n", &f, p, *p, f);p--;DBG_PRINTF("p= 0x%08X, p_g = %d\r\n", p, *p);return a+f;
}int func_va_list2(volatile int a, ...){volatile int *p;p = (int*)&a;DBG_PRINTF("p= 0x%08X, p_a = %d\r\n", p, *p);p++;DBG_PRINTF("p++;\r\n");DBG_PRINTF("p= 0x%08X, p_b = %d\r\n", p, *p);p++;DBG_PRINTF("p= 0x%08X, p_c = %d\r\n", p, *p);p++;DBG_PRINTF("p= 0x%08X, p_d = %d\r\n", p, *p);p++;DBG_PRINTF("p= 0x%08X, p_e = %d\r\n", p, *p);p++;DBG_PRINTF("p= 0x%08X, p_f = %d\r\n", p, *p);p++;DBG_PRINTF("p= 0x%08X, p_g = %d\r\n", p, *p);return a+(*p);}int func_va_list3(volatile int a, volatile int b, ...){volatile int *p;p = (int*)&a;DBG_PRINTF("p= 0x%08X, p_a = %d, &a = 0x%08X\r\n", p, *p, &a);p++;DBG_PRINTF("p++;\r\n");DBG_PRINTF("p= 0x%08X, p_b = %d, &b = 0x%08X\r\n", p, *p, &b);p++;DBG_PRINTF("p= 0x%08X, p_c = %d\r\n", p, *p);p++;DBG_PRINTF("p= 0x%08X, p_d = %d\r\n", p, *p);p++;DBG_PRINTF("p= 0x%08X, p_e = %d\r\n", p, *p);p++;DBG_PRINTF("p= 0x%08X, p_f = %d\r\n", p, *p);p++;DBG_PRINTF("p= 0x%08X, p_g = %d\r\n", p, *p);return a+(*p);}int func_va_list4(volatile int a, volatile int b, ...){volatile int *p;p = (int*)&a;DBG_PRINTF("p= 0x%08X, p_a = %d, &a = 0x%08X\r\n", p, *p, &a);p = (int *)&b;DBG_PRINTF("p = (int *)&b;\r\n");DBG_PRINTF("p= 0x%08X, p_b = %d, &b = 0x%08X\r\n", p, *p, &b);p++;DBG_PRINTF("p= 0x%08X, p_c = %d\r\n", p, *p);p++;DBG_PRINTF("p= 0x%08X, p_d = %d\r\n", p, *p);p++;DBG_PRINTF("p= 0x%08X, p_e = %d\r\n", p, *p);p++;DBG_PRINTF("p= 0x%08X, p_f = %d\r\n", p, *p);p++;DBG_PRINTF("p= 0x%08X, p_g = %d\r\n", p, *p);return a+(*p);}int func_va_list5(volatile int a, volatile int b, volatile int c, volatile int d, volatile int e, volatile int f, int g){volatile int *p;p = (int*)&a;DBG_PRINTF("&a = 0x%08X, p= 0x%08X, p_a = %d, a = %d\r\n", &a, p, *p, a);p--;DBG_PRINTF("p--;\r\n");DBG_PRINTF("&b = 0x%08X, p= 0x%08X, p_b = %d, b = %d\r\n", &b, p, *p, b);p--;DBG_PRINTF("&c = 0x%08X, p= 0x%08X, p_c = %d, c = %d\r\n", &c, p, *p, c);p--;DBG_PRINTF("&d = 0x%08X, p= 0x%08X, p_d = %d, d = %d\r\n", &e, p, *p, d);p--;DBG_PRINTF("&e = 0x%08X, p= 0x%08X, p_e = %d, e = %d\r\n", &e, p, *p, e);p--;DBG_PRINTF("&f = 0x%08X, p= 0x%08X, p_f = %d, f = %d\r\n", &f, p, *p, f);p--;DBG_PRINTF("&g = 0x%08X, p= 0x%08X, p_g = %d, g = %d\r\n", &g, p, *p, g);return a+f;
}int main(void){WDTCTL = WDTPW | WDTHOLD;   // 关闭看门狗Clock_System_Init();        // MCLK=SMCLK=8M ACLK=32768(有误差)UARTA0_Init();              // 用于printf的串口puts("~~~~~|MSP430 RUN>>>>\r\n");DBG_PRINTF("------------------------------------func_va_list\r\n");func_va_list(1, 2, 3, 4, 5, 6, 7);DBG_PRINTF("------------------------------------func_va_list2\r\n");func_va_list2(1, 2, 3, 4, 5, 6, 7);DBG_PRINTF("------------------------------------func_va_list3\r\n");func_va_list3(1, 2, 3, 4, 5, 6, 7);DBG_PRINTF("------------------------------------func_va_list4\r\n");func_va_list4(1, 2, 3, 4, 5, 6, 7);DBG_PRINTF("------------------------------------func_va_list5\r\n");func_va_list5(1, 2, 3, 4, 5, 6, 7);while(1);
}

实验结果

~~~~~|MSP430 RUN>>>>
------------------------------------func_va_list
&a = 0x00002bdc, p= 0x00002bdc, p_a = 1, a = 1
p--;
&b = 0x00002bde, p= 0x00002bda, p_b = 1, b = 2
&c = 0x00002be0, p= 0x00002bd8, p_c = 1, c = 3
&d = 0x00002bec, p= 0x00002bd6, p_d = 0, d = 4
&e = 0x00002bec, p= 0x00002bd4, p_e = 11220, e = 5
&f = 0x00002bee, p= 0x00002bd2, p_f = 0, f = 6
p= 0x00002bd0, p_g = 11216
------------------------------------func_va_list2
p= 0x00002bec, p_a = 1
p++;
p= 0x00002bee, p_b = 2
p= 0x00002bf0, p_c = 3
p= 0x00002bf2, p_d = 4
p= 0x00002bf4, p_e = 5
p= 0x00002bf6, p_f = 6
p= 0x00002bf8, p_g = 7
------------------------------------func_va_list3
p= 0x00002be2, p_a = 1, &a = 0x00002be2
p++;
p= 0x00002be4, p_b = 6904, &b = 0x00002bec
p= 0x00002be6, p_c = 0
p= 0x00002be8, p_d = 428
p= 0x00002bea, p_e = 1
p= 0x00002bec, p_f = 2
p= 0x00002bee, p_g = 3
------------------------------------func_va_list4
p= 0x00002be2, p_a = 1, &a = 0x00002be2
p = (int *)&b;
p= 0x00002bec, p_b = 2, &b = 0x00002bec
p= 0x00002bee, p_c = 3
p= 0x00002bf0, p_d = 4
p= 0x00002bf2, p_e = 5
p= 0x00002bf4, p_f = 6
p= 0x00002bf6, p_g = 7
------------------------------------func_va_list5
&a = 0x00002bdc, p= 0x00002bdc, p_a = 1, a = 1
p--;
&b = 0x00002bde, p= 0x00002bda, p_b = 1, b = 2
&c = 0x00002be0, p= 0x00002bd8, p_c = 1, c = 3
&d = 0x00002bec, p= 0x00002bd6, p_d = 0, d = 4
&e = 0x00002bec, p= 0x00002bd4, p_e = 11220, e = 5
&f = 0x00002bee, p= 0x00002bd2, p_f = 0, f = 6
&g = 0x00002bf0, p= 0x00002bd0, p_g = 11248, g = 7

 

  相关解决方案