C语言中有误导性质或是不适当的特性与C语言的简洁有关(部分与符号的过度复用有关),有些则与操作符的优先级有关。

C语言里,许多符号是被“重载”的——在不同的上下文环境里有不同的意义。甚至有些关键字也被重载而具有好几种意义,这也是C语言的范围规则对程序员不那么清晰的主要原因。
表展示C语言中类似的符号是如何具有多种不同意义的。

符号 意义
static 1.在函数内部,表示该变量的值在各个调用间一直保持延续性。
2.在函数这一级,表示该函数只对本文件可见
extern 1.用于函数定义,表示全局可见(属于冗余的)
2.用于变量,表示它在其他地方定义
void 1.作为函数的返回类型,表示不返回任何值
2.在指针声明中,表示通用指针的类型
3.位于参数列表中,表示没有参数
* 1.乘法运算符
2.用于指针,间接引用
3.在声明中,表示指针
& 1.位的AND操作符
2.取地址操作符
= 1.赋值符
== 1.比较运算符
<= 1.小于等于运算符
<<= 1.左移复合赋值运算符
< 1.小于运算符
2.#include指令的左定界符
() 1.在函数中,包围形式参数表
2.调用一个函数
3.改变表达式的运算次序
4.强制类型转换
5.定义带参数的宏
6.包围sizeof操作符的操作数(如果它是类型名)

除此之外,还有一些符号具有多个容易混淆的意思。重载存在的问题之处如下面语句所示:

1
p = N * sizeof * q;

这里是一个乘号还是两个乘号?
答案是这里只有一个乘号,因为sizeof操作符把指针q指向的东西(*q)作为操作数,它返回q所指向对象的类型的字节数,便于malloc函数分配内存。当sizeof的操作数是个类型名时,两边必须加上括号(这常常使人误以为它是个函数),但操作数如果是个变量则不必加括号。
一个更复杂的例子:

1
a = sizeof(int) * p;

是int的长度乘以p?或者是把未知类型的指针p强制转换为int,然后进行sizeof操作?
实际检验一下:

代码段1:

1
2
3
4
5
6
7
int main(void){
int *q;
int p;
p = sizeof(int) * q;
printf("%d\n",p);
return 0;
}

编译出错:

1
2
p = sizeof(int) * q;
error: invalid operands to binary * (have 'unsigned int' and 'int *')

明显这样并不是把未知类型的指针p强制转换为int,然后进行sizeof操作,而是编译器把星号(*)当作乘号来处理了,但由于左右操作数类型不匹配而报错。

代码段2:

1
2
3
4
5
6
7
int main(void){
int *q;
int p = (int) * q;
p = sizeof p;
printf("%d\n",p);
return 0;
}

这样写便为把未知类型的指针p强制转换为int,然后进行sizeof操作。
运行输出:
4

代码段3:

1
2
3
4
5
6
7
int main(void){
int *q;
int p;
p = sizeof(int) * (int)q;
printf("%d\n",p);
return 0;
}

对指针p的地址进行强制转换,指针p强制转换为int,然后乘上sizeof(int)。

代码段4:
另外一种对该句代码的合理解释

1
2
3
4
5
6
7
int main(void){
int q = 2;
int p;
p = sizeof(int) * q;
printf("%d\n",p);
return 0;
}

q为int型变量,p = int的长度乘以q,结果输出:
8

让一个符号所表达的意思越多,编译器就越难检测到这个符号在你的使用中所存在的异常情况。