1、常量表达式在编译时求值,而非在运行时求值
2、数值常量、字符常量、字符串常量、枚举常量 enum moths {JAN=1, FEB, MAR, APR}
3、外部变量、局部变量(静态变量、自动变量)。外部变量、静态变量未初始化自动置为0,自动变量未初始化置为无效值。const限定的值无法改变。
4、习惯上把变量和函数的extern声明放在一个单独的头文件中。
5、贪心法。c编译器将尽可能多的字符当做一个操作符,知道与其后的字符不可组成一个操作符。"/*"将是注释的开始,“/ *”将是两个操作符。a---b与a -- - b相同,与a - -- b 不同。
6、类型转换。运算符左右将窄的转换成宽的,赋值运算符右侧转换成左侧类型,函数参数调用默认转换成int和double;强制类型转换,自动转换为声明的函数原型中的参数类型。
7、自增自减。慎用,何时增减令人疑惑。s[i]=c;i++;与s[i++]=c结果相同。
8、& 经常用来屏蔽某些二进制位,| 经常用来将某些二进制位置为1。>>与<<操作unsigned类型,空出部分用0填补;而操作signed类型,则不一定,用符号位填补或者0填补。
9、C语言未指定同一运算符多个操作数的计算顺序,未指定函数各参数的求值顺序,慎用。
10、将声明中的变量名和末尾;去掉,外套()可得类型转换符。
11、个人理解,typedef中自定义符号可表示除其之外所有符号代表的类型。例如 typedef int SIZE 中可用SIZE表示整型。void(*h)() 声明一个返回值为void的函数,h为该函数的指针。void(*)() 则表示一个“指向返回值为void类型的函数的指针”的类型,外加括号可为该类型转换符。故而(void(*)())0可表示地址为0的函数的指针。
typedef void (*funcptr)(); funcptr可用来代表 void(*)()类型(*(funcptr)0)(); 表示执行在首地址0的函数
12、goto error; error: ; 尽量少使用,但非必须
13、静态变量static,修饰外部变量,该变量只能被该文件访问,同一程序其他文件中的函数不可访问;修饰局部变量,则局部变量只能在此函数中使用,但一直占据内存空间。
14、#include 将文件名替换为文件内容。
15、#define 自定义处开始到该源文件尾处结束;可替换任意文本,包括程序块;形参不可用带字符串的形参替换,但可以#作为前缀将实参扩展为带引号的字符串
#define dprint(expr) printf(#expr " = %g\n", expr)
则 dprint(x/y) 被扩展为 printf("expr" " = %g\n", x/y), 等价于printf("x/y = %g\n", x/y);
##可用来连接实参
#define paste(f, b) f ## b
则 paste(name,1) 将建立标号 name1
16、#if #endif #define defined #ifdef #ifndef
17、数组名与指针在操作连续存储空间是等价的。但指针是变量,可以进行pa=a,++pa等操作;数组名指代整个数组不是变量,不可进行a=pa,++a等操作。也就不难理解sizeof(a)是整个数组a占用的空间,而sizeof(pa)只是指针变量占用的存储空间。
18、char s[] = "snow"定义的是字符串变量,所以可以更改s为S;char * s = "snow"定义的是字符串常量,s仅仅指向它,更改操作未定义,不同编译器实现不同。
19、scanf()函数忽略格式串中的空格与制表符,读取输入值时跳过所有空白符,故可以跨行搜索。而scanf()下一次读取位置为上一次成功转换的下一个字符。故,scanf("%s", &s1);gets(s2);s2'\n'直接读取'\n',从而返回空值。
可用禁止符*,表示禁止下一个字符段,跳过该输入字段。
scanf("%s%*c", s1);gets(s2);
如果使用scanf(%s%*d%*c, s1);gets(s2)则可忽略下一数字字段。
输入:yueer 123
love
则 s1="yueer" s2="love"