c语言使用 printf函数调试(查找段错误)
-
宏定义
------在预处理阶段,宏被原样展开替换
//#define 宏名 字串(可以是整数、浮点数、字符串、表达式。。。)
#define PI 3.14 //自定义宏
#define STR “abc” //自定义宏 -
printf()中的预定宏
FILE 正在编译的文件名
LINE 文件当前的行号
FUNCTION 当前所在的函数名 == func
DATE 预编译文件的日期
TIME 预编译文件的时间
STDC 判断编译器是否遵循ANSI C,是则为1
其中, __LINE__和__STDC__是整型常量,其余为字符串常量。 -
使用案例1
void func(void)
{
printf("%d\n",__LINE__); //打印当前执行行号
printf("%s\n",__FUNCTION__); //当前所在的函数名 == __func__
}
int main(int argc,char *argv[])
{
printf("%d\n",__LINE__); //打印当前执行行号
printf("%s\n",__FUNCTION__); //当前所在的函数名 == __main__
printf("%s\n",__DATE__); //预编译文件的日期
printf("%s\n",__TIME__); //预编译文件的时间
func();
}
-
段错误的处理
常用段错误的处理方法是:二分法
出现段错误后,步骤如下:第一步,我们可以在程序比较中间的位置加入printf("%d\n",LINE);//打印行号
第二步,编译运行程序,查看 ‘行号’ 的信息是否有打印出来,如果没有打印,说明段错误出现在当前 ‘行号’ 的前面。如果 ‘行号’ 的信息打印出来了,则说明段错误出现在当前 ‘行号’ 的后面。
第三步,如果段错误出现在 ‘行号’ 前面(后面),在前面(后面)那一部分代码 中 ,在比较中间的位置加入printf("%d\n",LINE);//打印行号
第四步,重复第二步,第三步。
第五步,重复第四步,直到最出段错误的那一行为止。
扩展
1.带参函数宏定义
//带参宏的参数a,b是表达式
#define MAX(a,b) ({\
typeof(a) _a = a;\ ----typeof是获取类型
typeof(b) _b = b;\
(void)(&_a == &_b);\----判断参数a b的类型是否一直
(_a)>(_b)?(_a):(_b);\
})
1. { }内包含的是一中不能赋值的表达式,因此在预处理宏替代时候回出错,因此加()转换成可以赋值的表达式。
2.(_a)>(_b)?(_a):(_b); 加括号是优先级的问题,_a是由于自增和自减的问题
3.(void)(&_a == &_b);判断参数a b的类型是否一致,不一致给出警告,不会报错的