关于可变参数va_list

TheBigBangWOW 2016-02-28 11:58:16
请问下图中的这段代码应该怎么理解?
VA_list我在网上看到的用法一般是用于定义可变参数函数用的,
但是这里很奇怪,va_list直接放到函数的参数里面了,
而且va_list之后没有va_start,直接出现va_arg,
请问这段代码应该怎么理解?

其中shape_t是一个自定义的结构体


...全文
197 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
pengzhixi 2016-03-03
  • 打赏
  • 举报
回复
难道在传进来之前就不能用va_start初始化过了。你可以看看这个函数使用的上下文。
赵4老师 2016-03-03
  • 打赏
  • 举报
回复
在64位系统下,写个使用va_xxxx的一小段代码,然后查看其对应的64位汇编指令,看看和在32位系统下对应的32位汇编指令在具体实现机制上是不是没啥本质区别。 声明不是我懒啊,我手边没64位系统。(只为失败找理由,不为成功找方法。
lm_whales 2016-03-03
  • 打赏
  • 举报
回复
引用 6 楼 zhao4zhong1 的回复:
调用约定 https://msdn.microsoft.com/zh-cn/magazine/9b372w95.aspx 在以上约定下,实现va_list,va_start,va_arg,va_end应该更复杂了吧。
va_list,va_start,va_arg,va_end 等宏 是C方式的 可变参数函数使用的 这些函数是 C 调用约定函数 所有参数 按照C调用约定 入栈传递 所以,C,C++ 实现起来,不用考虑 函数调用约定 所有比 int 短的整型(包括指针),一律按照整形处理 也就是整型参数 只有 int ,long ,long long 三种长度的整型 float ,double 按照 double 长度处理 long double 类型,由于种种原因,标准没有统一长度,因此不再考虑之列 至于其他调用约定,会被忽视的 除非编译器有更好的办法,不会实现为其他调用约定。 估计C++成员函数,定义为C式参数可变函数(不是C++那种模板参数可变函数), 除了 this 指针的传递外,其它参数也是C调用约定的传递方式。
lm_whales 2016-03-01
  • 打赏
  • 举报
回复
va_list 本身并不复杂,通常的实现只是个指针类型。 真正复杂的是 va_start, va_arg, 而 va_end 也很简单,大部分实现都是什么都不做, 但是考虑到,某些系统可能会需要做收尾处理, 所以这个 宏 的存在和调用,也是必要的, 。 实际上,char ,short 等类型 va_arg 实现起来,没有难度, 但是某些编译器比如 GCC 考虑的太过奇葩了一点 于是 va_arg 就只能取 指针,int,long ,以及 更新的 long long ,double 等类型了 float 是唯一的 va_arg 难以处理的类型,因为不论从对齐还是别的方面来考虑, 不从语言上想办法, 仅仅靠宏,和C 现有语法语义, 难以实现 va_arg 对 float 的处理。
galiniur0u 2016-03-01
  • 打赏
  • 举报
回复
不知道楼主是否自己尝试编写一个可变参数程序
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>

void print(va_list args)
{
    int i;
    for(i = 0; i < 5; i ++)
    {
        printf("%d ", va_arg(args, int));
    }
    va_end(args);

}

int forVaArg(int x, ...)
{
    va_list args;
    int i;
    va_start(args, x);
    print(args);
    return 0;
}

int main(int argc, char *argv[])
{
    forVaArg(4, 5, 5, 2, 1, 8, 9);
    return 0;
}
如果注释掉va_start就会打印出错误的数据,因为找不到参数起始地址。书中估计因为篇幅的原因有部分代码省略掉了。
赵4老师 2016-03-01
  • 打赏
  • 举报
回复
调用约定 https://msdn.microsoft.com/zh-cn/magazine/9b372w95.aspx 在以上约定下,实现va_list,va_start,va_arg,va_end应该更复杂了吧。
  • 打赏
  • 举报
回复
va_list 也是一个变量啊,当然可以做参数使用。
LubinLew 2016-02-29
  • 打赏
  • 举报
回复
应该在函数CreatePoint中调用了吧。

           #include <varargs.h>

           void
           foo(va_alist)
               va_dcl
           {
               va_list ap;

               va_start(ap);
               while (...) {
                   ...
                   x = va_arg(ap, type);
                   ...
               }
               va_end(ap);
           }

赵4老师 2016-02-29
  • 打赏
  • 举报
回复
理解讨论之前请先学会如何观察! 计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构…… 对学习编程者的忠告: 多用小脑和手,少用大脑、眼睛和嘴,会更快地学会编程! 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步Debug版对应汇编一行! 单步Debug版对应汇编千行不如单步Release版对应汇编一行! 不会单步Release版对应汇编?在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有,然后在IDE中运行。(一般人我不告诉他!) VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。 对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。 VS IDE中,在不明白的符号上点鼠标右键,选转到定义或转到参考。

69,371

社区成员

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

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