相同指针陷阱
这是一个将yp指针的值加到xp指针两次的函数。
void fun1(int *xp, int *yp)
{
*xp += *yp;
*xp += *yp;
}
这个代码表面一看可以优化成这样
void fun1(int *xp, int *yp)
{
*xp += 2 * *yp;
}
但是如果yp于xp指针指向的是同一个地址,那么情况就会变成这样,此时*xp的结果会是原先的4倍。
void fun1(int *xp, int *yp)
{
*xp += *xp;
*xp += *xp;
}
修改了后会变成这样,结果只是原先的三倍。
void fun1(int *xp, int *yp)
{
*xp += 2 * *xp;
}
全局变量声明陷阱
- 在编译时,编译器向汇编器输出每个全局符号,或者强或弱,而汇编器把这个信息隐含地编码在可重定位目标文件的符号表里。函数和已初始化的全局变量是
强符号
,未初始化的全局变量是弱符号
。
Linux链接器通过下面的规则来处理多重定义的符号名:
- 不允许有多个同名的强符号。
- 如果有一个强符号和多个弱符号同名,那么选择强符号。
- 如果有多个弱符号同名,那么从这些弱符号中任选一个。
例如,假设我们试图编译和链接下面两个C模块。
/*foo1.c*/
int main()
{
return 0;
}
/*bar1.c*/
int main()
{
return 0;
}
-
这种情况中,连接器一定会生成一条错误信息,因为强符号main被定义了多次。
-
相似的,如果是已初始化的全局变量也会报重定义。
/*foo1.c*/
int x = 20201127;
int main()
{
return 0;
}
/*bar1.c*/
int x = 20201128;
int main()
{
return 0;
}
- 但是如果有其中一个文件中的同名全局变量没有初始化,那么强全局变量只有一个,编译是可以通过的,这时候编译器只会报警告。
- 如果是一个模块极其庞大的程序,检查起来更加困难,会造成不可预料的后果。
- 甚至有可能全局变量名字一样,但是类型不一样,这出现问题起来,更加的危险。
/*foo1.c*/
int x = 20201127;
int main()
{
return 0;
}
/*bar1.c*/
int x;
int main()
{
return 0;
}