#1 词法分析
词法分析的最大匹配原则:在编译器遇到“空白” (空格、回车、制表符等)之前,以能够取得的、有意义的、最长的字符串作为记号。
#2 注释
/**/注释方式不支持嵌套注释
注释三原则:
1 字符串里的注释符不起注释作用
2 注释符里的双引号不起表示字符串的作用
3 如果情况混乱则从头找起
#3 新数据类型的定义
建议使用typedef,定义方法与声明变量类似,只不过前面加上typedef。
应注意:
1 typedef与变量一样有可视范围,并且内层定义可以覆盖外层定义。
2 同一作用域内不能使用相同的名字定义不同的数据类型。
3 typedef的作用范围最大只能是他所在的编译单元,故不同C文件里面的typedef互相独立,完全没有任何限制。
对于能完成类似功能的#define,执行的仅仅是低级的记号替换,又是会出问题。如:
#define char* String;
String infile,outfile;
经预编译转换为:
char* infile,outfile;//outfile 成了char型
另外,typedef也有局限性,即其定义的类型不能再和其他类型组合使用:
unsigned INT32 a;//wrong
在与const一起使用时,要注意const修饰的是整个typedef定义的类型:
typedef char *String;
const Sting s;
等同于
char *const s;//s是指向char的const指针
#4 #pragma和_Pragma
C90中引入#pragma,为特定的编译器提供特定的编译指示。因为其与具体平台相关,所以在使用时最好结合其他的预处理指令(用于检测平台)一起使用。
C99中引入_Pragma:
_Pragma ("XXXXX")
和#pragma相比优点是可以利用宏定义来简化书写,而#pragma由于有#,在宏定义中#有特殊含义,所以不可以通过宏定义简化书写。
#5 void
功能1:用于函数参数检查。如果一个无参数的函数这样写:double fun( );则编译器无法对其进行参数匹配检查,但是如果这样写double fun(void);就可以进行检查了。
功能2:用于void指针 void *,可以指向除了函数外的任何对象。并且该指针在C中和除函数指针外的任何指针相互转化时不需要强制类型转换。(C++中把其他类型指针赋给void指针也不需强制转换,但把void指针赋给其他类型指针需要强制转换)。
功能3:用于C中NULL的定义:#define NULL (void *) 0(C++中是这样定义的:#define NULL 0,因为0可以直接赋给任何指针)
#6 字符串
字符串是常量的一种,安排在只读数据区,不能修改:
char *p="ABCDE";
但这样就可以修改了:
char p[ ]="ABCDE";
因为在main函数的栈里为p分配了空间 ,并把字符串复制到了其中。
#7 C-V限定词
C-V限定词指const和volatile两个修饰符。
const
---要清楚const修饰的是什么对象,可以去掉类型符号:
const int =1;//a不可变
const int *p=&a;//(*p)不可变
int *const p=&a;//p不可变
const主要用于函数的参数限定,以保证该参数不会被调用的函数修改。
const在C和C++中的区别:
1 C++把以常量赋值的const变量看作编译期常数,C没有这种功能。
const int BUFSIZE=1024;
char buf[BUFSIZE];//OK only in C++
2 C++默认const变量的链接性质是内部的,而C默认是外部的。
const int a=0;
int main(){}
3 C只允许用常量初始化const外部变量,C++无此限制。
int f(void);
cosnt int a=f( );//OK only in C++
int main(){}
volatile
---告诉编译器这个变量可能会被外部事件修改。