1、指针与NULL
下面这段代码会报错:
{ int *a = NULL; *a = 3; printf("%d",*a); }
指针初始化为NULL,还是没有分配内存,所以会报错。指针是个变量,就是个装地址的变量,是变量就可以重复使用。
而平时之所以让指针指向NULL,是防止误用了野指针修改随机内存。但具体使用前一定要保证已分配内存了。
2、NDEBUG与assert
头文件assert.h定义的宏受NDEBUG的影响.如果预程序在处理这个头文件时已经定义了NDEBUG,assert宏的内容就定义为空,这意味着assert宏不在起作用.所以,可以在最终发布程序的时候可以使用-DNDEBUG关闭断言功能或者把#define NDEBUG加到每个源文件中,但这条语句必须放在#include <assert.h>之前.
1 #include<stdio.h> 2 #define NDEBUG //要加在#include<assert.h>前面 #include<assert.h> 3 int main() 4 { 5 int x = 0; 6 assert(x); 7 printf("aa "); return 0; 8 }
trace(),assert()都只是在DEBUG的模式下才起作用的,如果定义了NDEBUG,编译器会认为是非DEBUG的模式(虽然编译出来的程序还是很大,而且还可以进行调试),此时trace(),assert()就没有用了.就如同你编译成release版的时候这些没有用一样。efine DEBUG 会重新打开调试开关
3、作用域与static、extern
举个例子,同一个工程下:
(1)在file.c中定义全局变量int a = 9,则在file2.c中不允许在全局下重定义变量a,但允许在语句"extern int a;"后可以访问file.c中的a。
(2)在file.c中定义全局变量static int a = 9,则a为file.c的文件作用域,在file2.c中无法访问。
4、不要写歧义的操作
比如下面这句话,对n的操作有歧义,究竟是左值中的n是n+1还是n呢?
ThreadHandle[n]=CreateThread( NULL, 0, comp, &varr[n++], 0, NULL );
类似的,f1()*f2()中,哪个先计算呢,在C++中,规定操作数计算顺序的的只有(), ?: 和 , ,此外其他操作符并未指定操作数的求值顺序,这类表达式的行为没有明确定义。
所以若操作数计算顺序会影响结果,最好可以写成更清晰地形式
1 ThreadHandle[n]=CreateThread( NULL, 0, comp, &varr[n], 0, NULL ); 2 n++; //不要把n的操作放在上面的表达式中,有歧义,易出错