今天给各位分享c语言debug宏如何使用的知识,其中也会对c++ debug怎么用进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
本文目录一览:
1、C语言中#if defined(__DEBUG__) # define Msg(msg) printf(“%s\n”, msg) #else # define Msg(msg) #endif2、C语言程序中为什么要使用debug宏3、C语言的宏(macro)是什么?怎样使用宏?
C语言中#if defined(__DEBUG__) # define Msg(msg) printf(“%s\n”, msg) #else # define Msg(msg) #endif
这是C语言的宏定义
#if defined(__DEBUG__) 如果定义了宏 __DEBUG__ 可以在编译选项中加这个宏,也可以在调用代码前用#define命令来定义这个宏,也可以不定义
# define Msg(msg) printf(“%s\n”, msg) 如果定义了宏 __DEBUG__,则遇到Msg(msg) 这样的语句,就会替换成printf(“%s\n”, msg)
#else
# define Msg(msg) 否则,没定义宏__DEBUG__,则遇到Msg(msg) ,就会替换成一个空语句。
#endif
C语言程序中为什么要使用debug宏
一个小程序试很多东西,改一会,思路和程序结构和参数设置全变样了,为了便捷地测试一些想要的C语言特性或运行结果,不停的在源程序上加对照组,改功能,相当于版本1、版本2、版本x同体~~~~printf不改怎么能行呢,给我打印个X出来看看对错――X刚才就不存在~!
还有一个不用debug宏的原因就是,某种程度上,debug宏开关的理念和把printf注释掉是一样的(个人理解)。
不过借口归借口,还是写的程序太小了,大一点的工程不用就不现实了,也不够“高大上”,话说回来,频繁改、程序小就是不用的借口了么?
恰巧昨天看了一道C语言面试题,认为至少那个网页给的答案是错的,于是想测试一下,题目如下:
请问下面程序有什么错误?int a[60][250][1000],i,j,k;for(k=0;k=1000;k++)for(j=0;j250;j++)for(i=0;i60;i++)a[i][j][k]=0;答案:把循环语句内外换一下
个人认为:错误关键在于k = 1000的那个等于号――越界了。跟顺序没关系。
==================================================================================================================
另外,即使排除k = 1000造成的数组越界,linux下仍然segmentation fault(core dumped),1000*250*60byte==15000000B,按估算空间没超,不知道为什么,是栈不够?反正我把1000改成100就行了~!
不过,这都是另一个或是另两个话题了,本次是对上边的那个“答案”质疑,想办法证明是错的,主要是为了在过程中引入debug宏。
==================================================================================================================
版本1:贴“答案”给出的方法,只改for循环的顺序:
int a[60][250][1000],i,j,k; for(i = 0;i 60;i++) for(j=0;j 250;j++) for(k = 0;k =1000;k++) a[i][j][k] = 0; for(i= 0;i 60;i++) for(j=0;j 250;j++) for(k = 0;k =1000;k++) printf(“%d/t”,a[i][j][k]);
明显的不行~!
版本2.0:首先,需要把那个k= 1000改成k 1000,来验证我的想法,证明“参考答案”错误。
#includemain(){ inta[60][250][1000],i,j,k; for(k = 0;k 1000;k++) for(j=0;j 250;j++) for(i = 0; i 60;i++) a[i][j][k] = 0; for(i = 0;i 60;i++) for(j=0;j 250;j++) for(k = 0;k 1000;k++) printf(“%d/t”,a[i][j][k]);}
结果segmentation fault(core dumped)了。
版本2.1:小修改。直接猜到了方向,把1000改成100了,这下程序运行正常。
版本3: k 100,赋值语句从0改成i+j+k了,for内层加上大括号,打印也升级为可读性更强的格式~
inta[60][250][100],i,j,k; for(i = 0;i 60;i++) for(j=0;j 250;j++) for(k = 0;k 100;k++){ a[i][j][k] = i+ j + k; printf(“a[%d][%d][%d] = %d/t”,i,j,k,a[i][j][k]); }
这些看起来很自然,但是,如果这些都是在一个源文件内改的,那会有多麻烦,而且原来的还找不回来,可能这里有比较好的一个法子,就是/*注释代码段*/
但是那样依然比较麻烦,开关的灵活性稍差,还有不小心注释错了范围的问题。其实即使有这点问题,也依然能用,但是既然已经这么麻烦了,何不尝试引入宏,养成一个比较有用的好习惯呢?因为这只是小test,正经的程序要大得多。
合体版本:
#include//通过宏激活三个版本,分别是数组越界,数组不越界但是仍然core dump,和一个改小数组的可执行(完成)版本。//#define WRONG_H_//#define K_EQ_1000_H_#define K_EQ_100_H_main(){#ifdef WRONG_H_ inta[60][250][1000],i,j,k; for(i = 0;i 60;i++) for(j=0;j 250;j++) for(k = 0;k = 1000;k++){ a[i][j][k] = i+ j + k; printf(“a[%d][%d][%d] = %d/t”,i,j,k,a[i][j][k]); }#endif#ifdef K_EQ_1000_H_ inta[60][250][1000],i,j,k; for(k = 0;k 1000;k++) for(j=0;j 250;j++) for(i = 0; i 60;i++){ a[i][j][k] = i+ j + k; printf(“a[%d][%d][%d] = %d/t”,i,j,k,a[i][j][k]); }#endif#ifdef K_EQ_100 int a[60][250][100],i,j,k; for(i = 0;i 60;i++) for(j=0;j 250;j++) for(k = 0;k 100;k++){ a[i][j][k] = i + j + k; printf(“a[%d][%d][%d] = %d/t”,i,j,k,a[i][j][k]); }#endif}
虽然是有点作用了,不过真正的debug可能耦合度低一点,代码重复度也应该小,本例中大部分代码重复(也可以只把循环中某一换用#ifdef和#endif括起来)。
既然知道改进方向,何不尝试一下,因为for顺序明显没影响,所以就统一了,降低耦合度么。不过数组定义的k等于1000和100那个没法拆,只能分开算了,我要体现出debug宏相对于注释的优势来。
首先,尝试拆分代码段,只对有区别的语句用宏分类,其次,不同宏之间可以用||来合并。不过还是有问题:不能使用下边这种只有if没有else的形式:
#include#define ORIGINAL_H_//#define K_EQ_1000_H_//#define K_EQ_100_H_#define FINAL_H_main(){#ifdef K_EQ_1000_H_||ORIGINAL_H_ inta[60][250][1000],i,j,k; for(k = 0;k 1000;k++)#endif#ifdef K_EQ_100_H_ || FINAL_H_ inta[60][250][100],i,j,k; for(k = 0;k 100;k++)#endif for(j=0;j 250;j++) for(i = 0; i 60;i++){ a[i][j][k] = i+ j + k; printf(“a[%d][%d][%d] = %d/t”,i,j,k,a[i][j][k]); }}
因为i,j,k等都需要声明定义,它们在#ifdef里边,不能保证一定声明。即使你真开了那个选项,也不被允许(编译器的事儿吧)。
那么折中,为了方便,我选择了相对简化解――“ if 配 else ”,并且把条件砍少了。具体应该怎样做,应该衡量自己的情况定。
include//排除绝对错误的用法和合并不大的改动,最后焦点就在k的大小,完全体是100,测试体是1000(假设目标是找core dumped的原因)//#define K_EQ_1000_H_//#define K_EQ_100_H_main(){#ifdef K_EQ_1000_H_ inta[60][250][1000],i,j,k; for(k = 0;k 1000;k++)#else inta[60][250][100],i,j,k; for(k = 0;k 100;k++)#endif for(j=0;j 250;j++) for(i = 0; i 60;i++){ a[i][j][k] = i+ j + k; printf(“a[%d][%d][%d] = %d/t”,i,j,k,a[i][j][k]); }}
这种方案也不是很完美,如注释所说,我简化了很多问题。不过,如果想把所有的语句和差别都弄上,也可以,不过视觉上会很乱~没有建设性,不做了,如果真想做,因为按句找差异进行拆分的思路已经有了(例如数组的声明和for循环的k部分),把其他所有想要的差异都一句一句拆分,然后给各个宏就完了。一句一句的拆分,比注释有点优越性了吧,如果这种一两句的分化特别多,成百上千行,那一句一句改是要死人的。
现在,把宏都注释掉,想要哪个版本的运行结果,只要取消注释就行了~既能运行错误版本去测试,又能运行“终极形态”完成任务,本例中宏的功能,更形象的说,是一个选择开关,不过,debug宏不就是个开关么?
虽然是比较粗糙的一种使用方式,不是“原装大厂”debug“的用法和教程,但是也算一种思路,更符合我们循序渐进的学习规律――你遇到困难或者效率低,然后解决这个障碍或者提高效率。其实最重要的还是你要在平时找机会引入各种应该掌握的功能,锻炼技巧,保持好习惯
C语言的宏(macro)是什么?怎样使用宏?
#define VERSION—STAMP “1.02″上例中所定义的这种形式的宏通常被称为标识符。在上例中,标识符VERSION_STAMP即代表字符串”1.02″——在编译预处理时,源代码中的每个VERSION_STAMP标识符都将被字符串“1.02”替换掉。以下是另一个宏定义的例子:#define CUBE(x)((x),(x)*(x))上例中定义了一个名为CUBE的宏,它有一个参数x。CUBE宏有自己的宏体,即((x)*(x)*(x))——在编译预处理时,源代码中的每个CUBE(x)宏都将被((x)*(x)*(x))替换掉。使用宏有以下几点好处: (1)在输入源代码时,可省去许多键入操作。(2)因为宏只需定义一次,但可以多次使用,所以使用宏能增强程序的易读性和可靠性。(3)使用宏不需要额外的开销,因为宏所代表的代码只在宏出现的地方展开,因此不会引起程序中的跳转。(4)宏的参数对类型不敏感,因此你不必考虑将何种数据类型传递给宏。需要注意的是,在宏名和括起参数的括号之间绝对不能有空格。此外,为了避免在翻译宏时产生歧义,宏体也应该用括号括起来。例如,象下例中这样定义CUBE宏是不正确的:denne CUBE(x) x * x * x对传递给宏的参数也要小心,例如,一种常见的错误就是将自增变量传递给宏,请看下例:#include stdio. h#include CUBE(x) (x * x * x)void main (void);void main (void){int x, y;x = 5;y = CUBE( + +x);printfC’y is %d\n” . y);}在上例中,y究竟等于多少呢?实际上,y既不等于125(5的立方),也不等于336(6* 7*8),而是等于512。因为变量x被作为参数传递给宏时进行了自增运算,所以上例中的CUBE宏实际上是按以下形式展开的:y = ((++x) * (++x) * (++x));这样,每次引用x时,x都要自增,所以你得到的结果与你预期的结果相差很远,在上例中,由于x被引用了3次,而且又使用了自增运算符,因此,在展开宏的代码时,x实际上为8,你将得到8的立方,而不5的立方。上述错误是比较常见的,作者曾亲眼见过有多年C语言编程经验的人犯这种错误。因为在程序中检查这种错误是非常费劲的,所以你要给予充分的注意。你最好试一下上面的例子,亲眼看一下那个令人惊讶的结果值(512)。宏也可使用一些特殊的运算符,例如字符串化运算符“#”和。连接运算符“##”。“#”运算符能将宏的参数转换为带双引号的字符串,请看下例:define DEBUG_VALUE(v) printf(#v”is equal to %d.\n”,v)你可以在程序中用DEBUG_VALUE宏检查变量的值,请看下例:int x=20;DEBUG_VALUE(x);上述语句将在屏幕上打印”x is equal to 20″。这个例子说明,宏所使用的“#”运算符是一种非常方便的调试工具。“##”运算符的作用是将两个独立的字符串连接成一个字符串。
c语言debug宏如何使用的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于c++ debug怎么用、c语言debug宏如何使用的信息别忘了在本站进行查找喔。