`int const a [5]`究竟是什么意思?

时间:2015-07-14 17:03:56

标签: c arrays const lvalue

考虑以下数组声明:

int const a[5];

从语言的语义角度来看,它是否完全等同于const int a[5]?假设是这种情况,两个声明基本上都会读作“ a是一个包含5个常量整数的数组”。

读取第一个声明的另一种方法是“ a是一个5个整数的常量数组”。

显然,这两个陈述逻辑上都暗示整个数组是不变的;如果一个数组由5个常量整数组成,则整个数组是常量。或者,如果整个数组是常量,那么它的所有值也是常量。

我知道“常量数组”的概念有点无意义,因为数组不是可修改的左值(也就是说,它们不能出现在赋值的左侧)。但是,是否有任何情况下这两个声明会产生不同的行为?

Cdecl.org拒绝第一个声明作为语法错误,而大多数当前编译器都接受它。)

编辑:

链接的副本询问const的顺序是否对普通变量很重要。对于数组,它有点混乱,所以我不认为这是重复的。

2 个答案:

答案 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

所以至少基于此,似乎并没有任何区别。