01. 调试相关的宏
在Linux使用gcc编译程序的时候,对于调试的语句还具有一些特殊的语法。
gcc编译的过程中,会生成一些宏,可以使用这些宏分别打印当前源文件的信息,主要内容是当前的文件、当前运行的函数和当前的程序行。
具体宏如下:
__FILE__ 当前程序源文件 (char*)
__FUNCTION__ 当前运行的函数 (char*)
__LINE__ 当前的函数行 (int)
这些宏不是程序代码定义的,而是有编译器产生的。这些信息都是在编译器处理文件的时候动态产生的。
「测试示例:」
#include <stdio.h>
int main(void)
{
printf("file: %s\n", __FILE__);
printf("function: %s\n", __FUNCTION__);
printf("line: %d\n", __LINE__);
return 0;
}
02. # 字符串化操作符
在gcc的编译系统中,可以使用#将当前的内容转换成字符串。
「程序示例:」
#include <stdio.h>
#define DPRINT(expr) printf("<main>%s = %d\n", #expr, expr);
int main(void)
{
int x = 3;
int y = 5;
DPRINT(x / y);
DPRINT(x + y);
DPRINT(x * y);
return 0;
}
「执行结果:」
deng@itcast:~/tmp$ gcc test.c
deng@itcast:~/tmp$ ./a.out
<main>x / y = 0
<main>x + y = 8
<main>x * y = 15
#expr表示根据宏中的参数(即表达式的内容),生成一个字符串。该过程同样是有编译器产生的,编译器在编译源文件的时候,如果遇到了类似的宏,会自动根据程序中表达式的内容,生成一个字符串的宏。
这种方式的优点是可以用统一的方法打印表达式的内容,在程序的调试过程中可以方便直观的看到转换字符串之后的表达式。
具体的表达式的内容是什么,有编译器自动写入程序中,这样使用相同的宏打印所有表达式的字符串。
//打印字符
#define debugc(expr) printf("<char> %s = %c\n", #expr, expr)
//打印浮点数
#define debugf(expr) printf("<float> %s = %f\n", #expr, expr)
//按照16进制打印整数
#define debugx(expr) printf("<int> %s = 0X%x\n", #expr, expr);
由于#expr本质上市一个表示字符串的宏,因此在程序中也可以不适用%s打印它的内容,而是可以将其直接与其它的字符串连接。
因此,上述宏可以等价以下形式:
//打印字符
#define debugc(expr) printf("<char> #expr = %c\n", expr)
//打印浮点数
#define debugf(expr) printf("<float> #expr = %f\n", expr)
//按照16进制打印整数
#define debugx(expr) printf("<int> #expr = 0X%x\n", expr);
「总结:」
#是C语言预处理阶段的字符串化操作符,可将宏中的内容转换成字符串。
03. ## 连接操作符
在gcc的编译系统中,##是C语言中的连接操作符,可以在编译的预处理阶段实现字符串连接的操作。
「程序示例:」
#include <stdio.h>
#define test(x) test##x
void test1(int a)
{
printf("test1 a = %d\n", a);
}
void test2(char *s)
{
printf("test2 s = %s\n", s);
}
int main(void)
{
test(1)(100);
test(2)("hello world");
return 0;
}
上述程序中,test(x)宏被定义为test##x, 他表示test字符串和x字符串的连接。
在程序的调试语句中,##常用的方式如下
#define DEBUG(fmt, args...) printf(fmt, ##args)
替换的方式是将参数的两个部分以##连接。##表示连接变量代表前面的参数列表。使用这种形式可以将宏的参数传递给一个参数。args…是宏的参数,表示可变的参数列表,使用##args将其传给printf函数.
「总结:」
##是C语言预处理阶段的连接操作符,可实现宏参数的连接。
04. 调试宏第一种形式
一种定义的方式:
#define DEBUG(fmt, args...) \
{ \
printf("file:%s function: %s line: %d ", __FILE__, __FUNCTION__, __LINE__);\
printf(fmt, ##args); \
}
「程序示例:」
#include <stdio.h>
#define DEBUG(fmt, args...) \
{ \
printf("file:%s function: %s line: %d ", __FILE__, __FUNCTION__, __LINE__);\
printf(fmt, ##args); \
}
int main(void)
{
int a = 100;
int b = 200;
char *s = "hello world";
DEBUG("a = %d b = %d\n", a, b);
DEBUG("a = %x b = %x\n", a, b);
DEBUG("s = %s\n", s);
return 0;
}
「总结:」
上面的DEBUG定义的方式是两条语句的组合,不可能在产生返回值,因此不能使用它的返回值。 |