在C语言中的常量数组

35

原问题:

如果我定义:

const int z[5] = {10, 11, 12, 13, 14}; 

它的意思是:

  1. 它是一个整数常量数组,即 z 指向的地址始终不变,但 z 的元素可以改变。

或者

  1. z 的每个元素都是一个常量,即它们的值永远不会改变。

编辑:

更多信息:

还有另一个变量:

const int *y = z;
func((int *) y);

其中 func 的定义如下:

void func(int y[]) {
    int i;
    for(i = 0; i < 5; i++) {
        y[i] = i; //y[i] can be set to any integer; used i as example
    }
}

在 func 中使用 y 遍历数组并更改每个元素。即使 z 的所有元素都是 const,这是否有效?


4
你尝试更改了 z[0] 吗? - Amit
6
z指向的地址无论如何都不会改变。无论如何,您可以使用http://cdecl.org/。 - juanchopanza
2
这没有意义。鉴于声明,任何试图修改z[0]的尝试都应该被编译器拒绝。请更新您的问题,并提供一个完整的自包含示例来证明这一点。 - Keith Thompson
1
@juanchopanza:这很难说。更有可能的是,原帖作者在某个地方犯了错误。 - Keith Thompson
1
你没有收到编译器警告,因为你将 y 的值强制转换为 int*。你告诉编译器 假装 y 指向非 const 数据。实际上,y 指向 const 数据,你向编译器撒了谎,你的代码行为未定义。强制类型转换,特别是指针类型转换,通常应该避免使用。 - Keith Thompson
显示剩余12条评论
2个回答

51

这意味着z的每个元素都是只读的。

z对象是一个数组对象,而不是指针对象;它没有指向任何东西。像任何对象一样,在其生命周期内z的地址不会改变。

由于对象z是一个数组,因此在大多数但不是所有情况下,表达式z被隐式转换为指向z [0]的指针表达式。该地址,就像整个数组对象z的地址一样,在对象的生命周期中不会改变。这种“转换”是表达式含义的编译时调整,而不是运行时类型转换。

要了解数组和指针之间(经常令人困惑的)关系,请阅读comp.lang.c FAQ第6节。

重要的是要理解“常量”和const是两个不同的概念。

如果某个东西是常量,那么它在编译时计算;例如,42(2+2)常量表达式

如果一个对象使用const关键字定义,那意味着它是只读的,而不一定是常量。这意味着您不能通过其名称尝试修改该对象,并且尝试通过其他方式修改它(例如,通过获取其地址并将其强制转换为非const指针)会产生未定义的行为。请注意,例如:

const int r = rand();

是有效的。r 是只读的,但它的值直到运行时才可以确定。


您能解释下这句话的意思吗:“z是一个数组,不是指针;它不指向任何东西”。而且“由于z是一个数组...被隐式地转换为指向z[0]的指针”请问它是指针还是不是? - Ziezi
1
@simplicisveritatis:数组不是指针。尝试获取两者的大小。但是,对于大多数用途,数组的名称会隐式转换为指向第一个元素的指针。 - too honest for this site
2
在 C 语言中,const 对象(与 C++ 不同)不一定是只读的。如果对象有任何写保护,那么实现就会留下这个决定。const 只是程序员不写入对象的保证。编译器可以依赖这个契约。在其他语言中,常量和文字之间没有实际区别。 - too honest for this site
2
如果它已经是一个指针,那么就不需要将其转换为指针了。数组对象包含一系列连续的元素。指针对象包含单个地址。它们是完全不同的东西。请再次阅读comp.lang.c FAQ的第6节;它比我有时间解释得更详细。 - Keith Thompson
1
@simplicisveritatis:好的。现在这两个句子清楚了吗? - Keith Thompson
显示剩余4条评论

1
在您的情况下,答案是:
  1. z 的每个元素都是一个常量,即它们的值永远不会改变。

您无法创建 const 数组,因为数组是对象,只能在运行时创建,而 const 实体在编译时解析。

因此,const 被解释为第一个示例中的内容,即应用于数组元素。这意味着以下内容是等效的: 您的示例中的数组需要初始化。

 int const z[5] = { /*initial (and only) values*/};
 const int z[5] = { /*-//-*/ };

这是一些关于const限定符和类型说明符的交换律

下面是一些例子来阐明常量的用法:

1.定义常量整数(不可重新分配)。在下面的两个表达式中,使用const是等效的:

int const a = 3;  // after type identifier
const int b = 4;  // equivalent to before type qualifier

2.常量指针定义(不允许指针算术或重新赋值):
int * const p = &anInteger;  // non-constant data, constant pointer

指向常量整型变量的指针定义(指向的整型变量的值不能被改变,但是指针本身可以)。
const int *p = &anInteger;  // constant data, non-constant pointer

12
在 C 语言中,一个数组只能在运行时创建吗?如果你将它定义为一个由 const 值组成的数组,则它将在编译时被创建。 - NikkyD
4
“const”实体在编译时解析。这是错误的。例如,“const int r = rand();”是有效的,但该值在运行时计算。 - Kolay.Ne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接