混合表达式中各个对象(如函数)的计算顺序是不确定的,x=f()+g()*h()
函数调用中各参数的计算顺序也不定。若参数之间或对象之间存在引用同一块内存的情况,该内存的结果将不可知。
续行符"\"后不可有任何字符,包括通常编辑模式下不可见的空白字符
通过指针指向的两数相除将引起语法错误,人ratio=*x/*y
局部变量在堆栈中分配,函数调用不可返回指向局部变量的指针
动态分配内存的原则是:谁申请谁释放,在一个函数中申请,在另外一个函数中释放的方法不可取
Linux下的软件质量保证工具splint,通过该工具可发现C代码中潜在的Bug
一般情况下,函数的参数按从左到右的顺序依次入栈,但编译器会尽可能的使用寄存器传递参数
与宏定义相比,枚举的优点:
#define定义的符号在编译时被丢弃,而枚举符号则通常一直到调试器中都可见
typedef的格式与变量声明完全一样,只是把定义的变量变成了以变量名为名字的数据类型,
标识符声明定义解读方法:先看标识符名的后缀操作符如(),[],然后看前缀操作符和修饰关键字
typedef 与 #define之间的区别
1、#define定义的别名可以用其他类型说明符(unsigned,const)等对宏类型名进行扩展,但typedef不行
2、typedef定义的类型可保证声明中所有变量均为同一种类型,而#define定义的类型则不能
数组的外部引用
int mango[100];
外部合法声明:extern int mango[];
非法声明:extern int *mango;
char *p=“abcd”; 字符串不可修改
char p[]=“abcd”; 字符串可以修改
cc编译选项:
-Ldir:指定链接时函数库寻找目录
-Rdir:指定运行时函数库寻找目录
静态库链接顺序安排
始终将-llibname 选项放于编译命令行最右边
静态库包之间的引用在链接时与顺序有关,.o文件之间的引用在链接时与顺序无关
不要轻易的让程序中的任何符号成为全局符号,除非有意把它们作为程序的接口,Linux内核中的非全局符号基本上都用static限制其于文件内
被调用函数可通过参数或全局指针访问调用它的函数的局部变量,如此可减少参数压栈操作,提高性能
C源码格式化工具:indent
二进制程序内存管理(内存泄漏)问题发掘工具:valgrind
程序性能优化工具
确定计算密集代码,以提供加快经常性事件参考
gprof:显式调用图配置的数据
(tcov、prof,语句执行次数统计工具)
在源码中用汇编语言插入单字节指令可打乱反汇编器
goto语句不能跳出当前函数
longjmp只能跳到曾经到过的地方(即调用过setjmp函数的地方)
标准代码优化技巧:
消除循环、函数代码就地扩展、公共子表达式消除、改进寄存器分配、省略运行时对数组边界的检查、循环不变量代码移动、操作符长度削减(如指数运算转为乘法运算,乘法运算转为移位运算或加法运算)
calloc:分配内存并清零
realloc:调整已分配内存的大小
有进程引起的内核内存泄漏,泄漏的内存不属于进程空间,很难发现
信号处理函数里调用标准库函数,其行为不可知
取下标操作符(即[])的两操作数满足交换律
用*alloc系列函数申请的内存不能分块逐步释放
(收起)