考虑以下数组声明:
int const a[5];
从语言的语义角度来看,它是否完全等同于const int a[5]
?假设是这种情况,两个声明基本上都会读作“ a是一个包含5个常量整数的数组”。
读取第一个声明的另一种方法是“ a是一个5个整数的常量数组”。
显然,这两个陈述逻辑上都暗示整个数组是不变的;如果一个数组由5个常量整数组成,则整个数组是常量。或者,如果整个数组是常量,那么它的所有值也是常量。
我知道“常量数组”的概念有点无意义,因为数组不是可修改的左值(也就是说,它们不能出现在赋值的左侧)。但是,是否有任何情况下这两个声明会产生不同的行为?
(Cdecl.org拒绝第一个声明作为语法错误,而大多数当前编译器都接受它。)
编辑:
链接的副本询问const
的顺序是否对普通变量很重要。对于数组,它有点混乱,所以我不认为这是重复的。
答案 0 :(得分:12)
它完全等同于
const int a[5]
是的,是的。
读取第一个声明的另一种方法是“a是一个5个整数的常量数组”。
不是真的。您的声明(如编写)专门将const
应用于数组元素。为了将const
应用于数组本身(而不是将其应用于数组元素),您必须执行类似
int (const a)[5];
但是这种声明在C语法中是无效的。
可以通过中间typedef
间接尝试将const
应用于数组本身
typedef int A[5];
const A a;
但是在这种情况下,根据语言规则,const
限定符“贯穿”到数组元素,整个事物等同于
const int a[5];
再次注意,上面的const A a;
不是立即等同于const int a[5];
。它实际上等同于前面提到的int (const a)[5];
(!)。 (这是偷偷摸摸int (const a)[5];
过去编译器防御的合法方式。)但是int (const a)[5];
非常短暂 - 它会被编译器立即转换为const int a[5];
。
如果数组由5个常量整数组成,则整个数组是常量。或者,如果整个数组是常量,那么它的所有值也是常量。
嗯,这不完全正确。 C语言确实区分了数组对象本身及其元素。从概念上讲,这些是不同的实体。例如,正如您自己所说,语言规范说数组是不可修改的左值。当然,这不会阻止数组元素可修改。
数组作为一个整体和单个数组元素之间的这种概念上的区别,加上const
的“通过”行为正是导致以下不愉快情况的原因
typedef int A[5];
A a;
const A *p = &a; // ERROR!!!
即。它打破了“正常”const-correctness规则,允许我们使用const T *
值初始化T *
指针。 (C ++故意更新了const-correctness规则,使上面的代码“按预期”运行,但C坚持拒绝它。)
答案 1 :(得分:1)
我把它放在一起:
#include <stdio.h>
int main()
{
int const a[5];
const int b[5];
int c[5];
a[0] = 1;
b[0] = 2;
c = a;
c = b;
}
gcc(4.1.2)吐了这个:
gcc -o /tmp/x2 /tmp/x2.c
/tmp/x2.c: In function ‘main’:
/tmp/x2.c:9: error: assignment of read-only location
/tmp/x2.c:10: error: assignment of read-only location
/tmp/x2.c:11: error: incompatible types in assignment
/tmp/x2.c:12: error: incompatible types in assignment
所以至少基于此,似乎并没有任何区别。