C 语言基础(va_list 和extern的用法)

①va_list方面

typedef char * va_list;
1.#define _INTSIZEOF(n)    ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )        //为了满足需要内存对齐的系统
2.#define va_start(ap,v)    ( ap = (va_list)&v + _INTSIZEOF(v) )                //ap指向第一个变参的位置,即将第一个变参的地址赋予ap
3.#define va_arg(ap,t)       ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )   /*获取变参的具体内容,t为变参的类型,如有多个参数,则通过移动ap的指针来获得变参的地址,从而获得内容*/
4.#define va_end(ap) ( ap = (va_list)0 )   //清空va_list,即结束

解析:这里写图片描述

define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

就是说如果实n是sizeof(int)的整数倍,那就是n,如果n%sizeof(int)!=0,那就返回n+1.

define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )

就是执行第一个可变参数

define va_arg(ap,t) ( (t )((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )

ap指向了可变参数下一个地址,返回的是变化之前ap指向的值。
举个例子说明吧
int y=va_arg(x,int);
宏展开成( (int )((x += _INTSIZEOF(int)) - _INTSIZEOF(int)) )
此时x指向下一个参数(x = x + _INTSIZEOF(int))
然后x再减去_INTSIZEOF(int)得到x未改变前的地址,
再将x所指向的int类型的值赋给y

也就就是说y取得x所指向的int类型的值,然后x指向下一个参数地址


1.
undefined reference to
在C语言中,修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。
如果你直接extern 声明一个变量是不行的,需要先定义
extern int a; //属于声明 extern int a = 10; //属于定义,同下
https://www.cnblogs.com/Lunais/p/5991135.html
https://blog.csdn.net/u012861978/article/details/78292844 更详细
2.
multiple definition of

具体分析如下,定义的话最好写在.c里面。写在.h里面的话,当别的代码包含此.h的时候就是重复定义了
https://blog.csdn.net/mantis_1984/article/details/53571758
3.
initializer element is not constant 。
全局变量是保存在静态存储区的,因此在编译的时候只能用常量进行初始化,而不能用变量进行初始化。在该程序中是用函数的返回值给变量进行初始化的,因此会出错。
在这里说一下全局变量和局部变量的在编译时的不同的处理方式,在程序编译的时候全局变量必须用常量进行初始化,也就是说直接在全局变量的内存地址直接存储变量的值;对于局部变量则在编译的时候不需要这样,编译的时候只需要将局部变量的赋值语句编译成机器代码,在程序运行到这里是在进行局部变量的赋值。

猜你喜欢

转载自blog.csdn.net/yanzhongqian/article/details/82591029