文本描述
在我的上一个专栏里,我讨论了为什么C++在实现将数据存入内存使用的规则要比C复杂一些的原因中的其中一个。关于这个话题我有很多话要说,不过在这之前,我想回复下面的疑问,这个问题是Baurer通过Email发给我的。
“我们对使用带有typedef的const饶有兴趣。我们希望你能评论这种情况。我想我们是否遇到了C语言中一些未知的规则。”
“我们在日立SH-2 32位RISC微控制器使用日立C编译器。我们认为下面的代码:
Typedef void *VP;
Const VP vetorTable[] = {… …};(1)
应该等同于:
Const void *vetorTable[] = {… …};(2)
但是连接器把在(1)中的vectorTable放于CONSTANT部分,把(2)中的放在了DATA部分”
“这是编译器正确的行为还是一个漏洞呢?”
这是一个正确的行为,它不是一个漏洞。你确实遇到了一些你明显不知道的C的规则。不要感觉到遗憾,不知道的并不是你一个人,许多其他的C和C++编程者对这些规则都感到迷茫,因此我在这个专栏里回答这个问题。
声明符:
这是第一个观点:
C和C++的每一个声明都有两个主要的部分:一串0个或多个声明修饰符,一串0个或多个声明符,用逗号分开。例如:
Static unsigned long int *x[N];
Declarationg specifier declarator
声明符就是要声明的名字,经常与像*,[],()和(在C++中)&连接在一起。就像你已经知道的那样,在声明符中这个符号*意味着“指向”,[]意思是“数组”。因此,*x[N]是一个声明符说明x是一个有N个指针元素组成的数组,类型是在类型修饰符中指定的类型。例如,
Static unsigned long int *x[N];
将x声明为这种类型的对象“有N个指向无符号长整型元素组成的数组。“(像后面讲的,关键字static对类型没有任何贡献。)
我怎么知道*x[N]是一个指针数组而不是指向数组的指针呢?它遵循这个原则:在声明符组中操作符的优先级与他们在表达式中的一致。
例如:如果你检查下最近的C或C++的优先级表,你会发现[]比*的优先级哟高。因此,在这个声明符中*x[N]意味着x是一个数组在它是一个指针之前。
圆括号在声明符中有两个作用,第一是作为函数调用操作符,二是分组。作为函数调用操作符时,()与[]的优先级相同,分组时()拥有最高的优先级。
例如,*f(int)是一个声明符,指定f是一个返回指针类型的函数。而(*f)(int)指定f是指向一个函数的函数指针。
声明符可能包含不止一个标识符。这个声明符*x[N]包含两个标识符,x和N。只有一个标识符是被声明的,被称为声明ID。其他的,如果还有的话,必须似乎在之前声明的了。例如在这个声明符中x是声明ID。
声明符不需要包含任何操作符。在一个简单的声明中:int n;声明符只是标识符n,没有任何操作符。
声明限定符
一些在声明符声明限定符可以是类型限定符诸如int,