- 各系统中的EOF
Windows Ctrl+Z
Linux Ctrl+D
数据类型及其初始化
-
上下限库文件
- int < limits.h >
- float < float.h >
-
无符号int溢出判断
a+b<a //a+b 上溢
a<b //a-b 下溢
- 有符号int溢出判断
a > INT_MAX - b //a+b 上溢
a < INT_MIN - b //a-b 下溢
- 浮点常量默认为double类型。常量数尾加L为long double, 加F为float
1.0 // double
1.0F // float
1.0L // long double
-
字符串常量有自己的内存空间。作实参时,传递的是常量地址
-
访问数组内容时,
array[N] == *(array+N) //前者为语法糖
-
给指针值默认为NULL,以防止野指针带来不可预测的问题
-
尽量不使用无符号类型。(除位段和二进制掩码)
-
\0
表示字符串的结束 -
NULL 表示空指针
-
const作用于右标识
const int * p; // *p的值不可改
int * const p; // p不可改
const int * const p; // *p和p皆不可改
- 多行String使用双引号结尾,新行再双引号开始
char str[] = "我是"
"小明";
-
使用char作小整数时,加上unsigned
-
中已定义有
int16_t int32_t
-
`sizeof(x) == sizeof x //事实上sizeof是运算符,并不是函数
-
任何类型的指针都可转换成void型指针
-
可以在结构中定义本身结构的指针
-
结构(struct)不能自加(不同于指针),也不能二者之间直接赋值
-
使用const防止参数在函数内被修改,在字符串处理函数中常见。
-
联合(union)体的初始化值必须与其第一个成员类型匹配
-
static变量的默认值是0
-
大部份情况下,
EOF == -1
-
“左值”是指在内存中有特定位置的东西,而不是完全指赋值的东西
-
array
和&array
的区别在于类型,值是相同的 -
array
是一个某类型的指针 -
&array
是一个某类型的数组的指针 -
size_t
是被定义成unsigned int
的自定义类型 -
注意字符串处理函数需要的是字符串而不是字符
-
当数字字符需要转换成对应的数字时,只需加或减去常数’0’ (字符) (回忆下ASCII码排列)
控制语句
-
c中的break,continue只能直接使用,单层跳出
-
可使用goto语句跳出多重循环 (但仍然不推荐使用)
while ( expr1 )
if ( expr2 )
goto quit;
quit: ; // 空语句代码段
- 在条件判断中,将常量(如果有)放置前面,防止错误赋值
if ( NULL == ptr)
error();
内存相关操作
-
内存溢出就是系统无法满足所需的内存空间
-
内存越界就是访问了不是申请得到的内存空间
-
内存泄漏就是程序在使用完动态申请的内存后没有释放内存,致使内存无法再次使用
-
malloc,calloc, realloc成功返回void指针,失败返回NULL
-
使用malloc(calloc, reallow)后应检查是否成功申请空间( == NULL )
-
使用临时变量来保存realloc返回的值,以避免当申请内存失败时,oldPtr的地址丢失造成内存泄露
-
把内存缓冲区的数据写到磁盘文件称为文件的关闭
优化建议
- 左移N位相当于操作数乘以2^N,前者速度更快。
int a = 2;
(a << 2) == (a * pow(2, 2));
// 但实际上,编译器在编译时,会自动把立方的操作变成位移。相反,后者更具可读性。
-
库函数更具有移植性
-
int快于char
-
头文件只包含不申请内存的声明语句,如函数原型,结构定义
-
关键字auto毫无用处
-
自定义结构名,先定义结构,再typedef名字
-
尽可能使用相同类型的值进行比较
函数相关
-
在语句结尾插入\表示语句未结束
-
void main()是错误的
-
使用fgets来避免溢出攻击(不要使用scanf或gets)
fgets( ..., stdin);
-
函数调用传参都是传递拷贝的值,但在数组名作实参时,形参得到是首元素的地址的拷贝,即传址
-
学会使用 int main(int argc, char **argv)
宏
-
宏会在预处理时先于编译进行
-
给宏加上(),以避免操作符优先级带来的未知问题
-
使用宏注释代码
#if 0
statements...
#endif