1.标准头文件#include <stdarg.h>
#define __va_rounded_size(TYPE) \
(((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
定义了取整后的TYPE类型的字节长度值,是int类型长度(4字节)的倍数。
#ifndef __sparc__
#define va_start(AP, LASTARG) \
(AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
#else
#define va_start(AP, LASTARG) \
(__builtin_saveregs (), \
AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
#endif
static int sprintf(char * str, const char *fmt, …)
C语言参数压栈,是从右往左的,满减栈,参数地址从高到低。让LASTARG = fmt,地址+变量自身大小的偏移,AP指向后面的可变参数列表。
#define va_arg(AP, TYPE) \
(AP += __va_rounded_size (TYPE), \
*((TYPE *) (AP - __va_rounded_size (TYPE))))
获取可变参数列表成员。先移动AP指向下一个参数,再获取当前的参数。
void va_end (va_list); /* Defined in gnulib */
#define va_end(AP)
在va_arg读完所有的参数后再被调用。(原理待进一步查找)
2.gcc编译包含自定义的头文件
gcc … -I<自定义文件相对路径>
进一步思考:多个路径,.c文件包含
3.调试中日志打印printf技巧
参考博客网址:https://blog.csdn.net/a651588/article/details/51790821
#define __DEBUG__
#ifdef __DEBUG__
#define DEBUG(format,...) printf("File: "__FILE__", Line: %05d: "format"/n", __LINE__, ##__VA_ARGS__)
#else
#define DEBUG(format,...)
#endif
4.gdb调试
使用gdb调试生成的可执行文件,需要在编译的时候添加生成调试信息的选项,gcc -c 文件 -g.