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操作符的操作数(如果它是类型名) |
除此之外,还有一些符号具有多个容易混淆的意思。重载存在的问题之处如下面语句所示:
p = N * sizeof * q;
这里是一个乘号还是两个乘号?
答案是这里只有一个乘号,因为sizeof操作符把指针q指向的东西(*q)作为操作数,它返回q所指向对象的类型的字节数,便于malloc函数分配内存。当sizeof的操作数是个类型名时,两边必须加上括号(这常常使人误以为它是个函数),但操作数如果是个变量则不必加括号。
一个更复杂的例子:
a = sizeof(int) * p;
是int的长度乘以p?或者是把未知类型的指针p强制转换为int,然后进行sizeof操作?
实际检验一下:
代码段1:
int main(void){
int *q;
int p;
p = sizeof(int) * q;
printf("%d\n",p);
return 0;
}
编译出错:
p = sizeof(int) * q;
error: invalid operands to binary * (have 'unsigned int' and 'int *')
明显这样并不是把未知类型的指针p强制转换为int,然后进行sizeof操作,而是编译器把星号(*)当作乘号来处理了,但由于左右操作数类型不匹配而报错。
代码段2:
int main(void){
int *q;
int p = (int) * q;
p = sizeof p;
printf("%d\n",p);
return 0;
}
这样写便为把未知类型的指针p强制转换为int,然后进行sizeof操作。
运行输出:
4
代码段3:
int main(void){
int *q;
int p;
p = sizeof(int) * (int)q;
printf("%d\n",p);
return 0;
}
对指针p的地址进行强制转换,指针p强制转换为int,然后乘上sizeof(int)。
代码段4:
另外一种对该句代码的合理解释
int main(void){
int q = 2;
int p;
p = sizeof(int) * q;
printf("%d\n",p);
return 0;
}
q为int型变量,p = int的长度乘以q,结果输出:
8
让一个符号所表达的意思越多,编译器就越难检测到这个符号在你的使用中所存在的异常情况。
网友评论