`int const a[5]` 到底是什么意思?
What does `int const a[5]` really mean?
考虑以下数组声明:
int const a[5];
从语言的语义角度来看,它是否完全等同于 const int a[5]
?假设是这种情况,这两个声明基本上读起来像“a 是一个包含 5 个常量整数的数组”。
读取第一个声明的另一种方法是“a 是一个包含 5 个整数的常量数组”。
显然,这两种说法在逻辑上都意味着整个数组是常量;如果数组由 5 个常量 int 组成,则整个数组是常量。或者,如果整个数组是常量,那么它的所有值也是常量。
我知道 "constant array" 的概念有点无意义,因为数组不是可修改的左值(也就是说,它们不能出现在赋值的左侧)。但是,在任何情况下这两个声明会产生不同的行为吗?
(Cdecl.org 拒绝第一个声明作为语法错误,而大多数当前编译器接受它。)
编辑:
链接副本询问 const
的顺序是否对普通变量有影响。对于数组,它有点混乱,所以我不认为这是重复的。
我把这个放在一起:
#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
所以至少从这一点来看,似乎没有任何区别。
is it exactly equivalent to const int a[5]
是的,是的。
The alternative way to read the first declaration would be "a is a constant array of 5 ints".
不是真的。如所写,您的声明专门将 const
应用于数组元素。为了将 const
应用于数组本身(而不是将其应用于数组元素),您必须执行类似
的操作
int (const a)[5];
但是这样的声明在 C 中在句法上是无效的。
可以通过中间类型定义
间接尝试将 const
应用于数组本身
typedef int A[5];
const A a;
但在这种情况下,根据语言规则,数组元素的 const
限定符 "falls through" 和整个事情等同于
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];
。
if an array consists of 5 constant ints, then the entire array is constant. Alternatively, if the whole array is constant, then all of its values are also constant.
嗯,这不完全正确。 C 语言确实区分了数组对象本身及其元素。从概念上讲,这些是不同的实体。例如,正如您自己指出的那样,语言规范说数组是 不可修改的左值 。当然,这并不妨碍数组元素可修改。
数组作为一个整体和单个数组元素之间的概念区别,加上 const
的 "fall through" 行为,正是导致以下令人不快的情况的原因
typedef int A[5];
A a;
const A *p = &a; // ERROR!!!
即它打破了 "normal" 常量正确性规则,该规则允许我们使用 T *
值初始化 const T *
指针。 (C++ 故意更新它的 const-correctness 规则以使上面的代码表现得 "as expected",但 C 坚持拒绝它。)
考虑以下数组声明:
int const a[5];
从语言的语义角度来看,它是否完全等同于 const int a[5]
?假设是这种情况,这两个声明基本上读起来像“a 是一个包含 5 个常量整数的数组”。
读取第一个声明的另一种方法是“a 是一个包含 5 个整数的常量数组”。
显然,这两种说法在逻辑上都意味着整个数组是常量;如果数组由 5 个常量 int 组成,则整个数组是常量。或者,如果整个数组是常量,那么它的所有值也是常量。
我知道 "constant array" 的概念有点无意义,因为数组不是可修改的左值(也就是说,它们不能出现在赋值的左侧)。但是,在任何情况下这两个声明会产生不同的行为吗?
(Cdecl.org 拒绝第一个声明作为语法错误,而大多数当前编译器接受它。)
编辑:
链接副本询问 const
的顺序是否对普通变量有影响。对于数组,它有点混乱,所以我不认为这是重复的。
我把这个放在一起:
#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
所以至少从这一点来看,似乎没有任何区别。
is it exactly equivalent to
const int a[5]
是的,是的。
The alternative way to read the first declaration would be "a is a constant array of 5 ints".
不是真的。如所写,您的声明专门将 const
应用于数组元素。为了将 const
应用于数组本身(而不是将其应用于数组元素),您必须执行类似
int (const a)[5];
但是这样的声明在 C 中在句法上是无效的。
可以通过中间类型定义
间接尝试将const
应用于数组本身
typedef int A[5];
const A a;
但在这种情况下,根据语言规则,数组元素的 const
限定符 "falls through" 和整个事情等同于
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];
。
if an array consists of 5 constant ints, then the entire array is constant. Alternatively, if the whole array is constant, then all of its values are also constant.
嗯,这不完全正确。 C 语言确实区分了数组对象本身及其元素。从概念上讲,这些是不同的实体。例如,正如您自己指出的那样,语言规范说数组是 不可修改的左值 。当然,这并不妨碍数组元素可修改。
数组作为一个整体和单个数组元素之间的概念区别,加上 const
的 "fall through" 行为,正是导致以下令人不快的情况的原因
typedef int A[5];
A a;
const A *p = &a; // ERROR!!!
即它打破了 "normal" 常量正确性规则,该规则允许我们使用 T *
值初始化 const T *
指针。 (C++ 故意更新它的 const-correctness 规则以使上面的代码表现得 "as expected",但 C 坚持拒绝它。)