va_arg第二个参数不解

FrankJT 2020-03-11 04:25:02
我在菜鸟驿站找到关于这个宏的描述是这样的:

type va_arg(va_list ap, type)

检索函数参数列表中类型为 type 的下一个参数

按照这个解释,我下面测试的就很有问题

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

char buffer[80];
int vspfunc(char* format, ...)
{
va_list aptr;
int ret;

va_start(aptr, format);
ret = vsprintf(buffer, format, aptr);
printf("test1 %d\n", va_arg(aptr, int));
printf("test2 %d\n", va_arg(aptr, char));
printf("test3 %s\n", va_arg(aptr, int));

va_end(aptr);
for (int i = 0; i < strlen(format); i++)
printf("%c", format[i]);
return(ret);
}

int main()
{
int i = 5;
int f = 27;
char str[50] = "tutoriasyiibai.com";

vspfunc("%d %d %s", i, f, str);
printf("\n\n%s", buffer);

return(0);
}


printf test1, test2, test3分别是int, char, int。参数压栈的顺序我知道,按照菜鸟驿站对这个宏的解释,我的理解是这样,比如
printf("test3 %s\n", va_arg(aptr, int))这句,我用的va_arg(aptr, int)返回的应该是int的数值,第一个test1时候找到了i=5,test3应该找f=27。但是结果是把char打印出来了。我写的是%s是后面发现打印出了char才改的。
还有printf("test2 %d\n", va_arg(aptr, char));结果把27那个打印出来了,也没有去找char。这是为什么?
...全文
277 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
FrankJT 2020-03-11
  • 打赏
  • 举报
回复
引用 7 楼 寻开心 的回复:
这个保护不是对所有的这种变长的函数都一样,只是printf函数 只是拿这个来说明一下, 这种变长参数,如果一个参数弄错了,会连带把其他的参数也在栈地址给搞错误,提取不到正确的结果了
是的,我去看了下头文件的定义,发现只是这样。我看那个菜鸟驿站的解释,还以为这个宏有什么内部机制,先搞个缓存哈哈
寻开心 2020-03-11
  • 打赏
  • 举报
回复
这个保护不是对所有的这种变长的函数都一样,只是printf函数
只是拿这个来说明一下, 这种变长参数,如果一个参数弄错了,会连带把其他的参数也在栈地址给搞错误,提取不到正确的结果了
寻开心 2020-03-11
  • 打赏
  • 举报
回复
关键是char*,是指针, 现在的指针是8个字节的, 和int 4个字节的不一样长。
printf函数的规则里面提到了,char,int都是入栈4字节,一样长。
float和double都是入栈8字节
这样保证了,你指定格式%c,%d的时候,无论传入进入是int还是char类型参数都可以正确获得
指定%f和%lf,传递float还是double都可以正确

但是指针不同啊, 它是8个字节, 它和类型不匹配,会导致其他的参数错乱了
FrankJT 2020-03-11
  • 打赏
  • 举报
回复
引用 2 楼 寻开心 的回复:
你想想printf,scanf,如果format和参数类型不匹配会如何
我发现打印的格式不对。。 我这样输入 vspfunc("%d %d %s", i, f, str); printf("test1 %d\n", va_arg(aptr, int)); printf("test2 %d\n", va_arg(aptr, int)); printf("test3 %s\n", va_arg(aptr, char*)); 这样打印没问题, 如果想 printf("test1 %d\n", va_arg(aptr, int)); printf("test3 %s\n", va_arg(aptr, char*)); printf("test2 %d\n", va_arg(aptr, int)); 这样打印就不行了。。我看说明,我的理解是找到那个类型的数据,然后读出来。所以我想的是,只有一个char*,我在什么顺序都可以唯一的读取到,而有两个int,所以int有顺序,对我这个例子,char*没顺序。 但是这样是报错的。所以这个只能按照顺序导出来对吧。。
FrankJT 2020-03-11
  • 打赏
  • 举报
回复
引用 1 楼 GKatHere 的回复:
vspfunc("%d %d %s", i, f, str); // int ,int, char*, 不是 int, char, int
我日,我没注意我写的是char不是char*。。。
FrankJT 2020-03-11
  • 打赏
  • 举报
回复
引用 1 楼 GKatHere 的回复:
vspfunc("%d %d %s", i, f, str); // int ,int, char*, 不是 int, char, int
我本来是对应的写的,你看我在3个printf对应输出的是 %d %d %s,我是想和输入的对照的。但是发现打印出来的不是我想要的结果。而且按照菜鸟驿站的说明,我的理解是char* 在int前输入或后都一样,第一个检查到的char* 就能打印出来。而两个int,所以这俩int才有顺序。
寻开心 2020-03-11
  • 打赏
  • 举报
回复
你想想printf,scanf,如果format和参数类型不匹配会如何
GKatHere 2020-03-11
  • 打赏
  • 举报
回复
vspfunc("%d %d %s", i, f, str); // int ,int, char*, 不是 int, char, int

70,037

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧