【问题标题】:Const arrays in CC中的常量数组
【发布时间】:2015-12-18 18:07:25
【问题描述】:

原问题: 如果我定义:

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,这是否有效?

【问题讨论】:

  • 您尝试更改z[0]吗?
  • z 指向的地址无论如何都不会改变。在任何情况下,您都可以使用cdecl.org
  • 这没有意义。鉴于该声明,任何修改z[0] 的尝试都应该被编译器拒绝。请用一个完整的独立示例来更新您的问题,以证明这一点。
  • @juanchopanza:这值得怀疑。 OP更有可能在某个地方犯了错误。
  • 您没有收到编译器警告,因为您将 y 的值转换为 int*。您是在告诉编译器假装 y 指向非const 数据。因为事实上y 指向const 数据,所以你对编译器撒了谎,你的代码有未定义的行为。通常应该避免强制转换,尤其是指针强制转换。

标签: c arrays constants


【解决方案1】:

表示z的每个元素都是只读的。

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

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

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

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

如果某事物是常量,则在编译时对其进行评估;例如,42(2+2)常量表达式

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

const int r = rand();

有效。 r 是只读的,但直到运行时才能确定其值。

【讨论】:

  • 你能解释一下你的意思吗:“z 是一个数组,不是一个指针;它没有指向任何东西”然后是“因为z是一个数组...被隐式转换为指针z[0]“它是不是指针?
  • @simplicisveritatis:数组不是指针。尝试取两者的大小。但是在大多数情况下,数组的 name 会隐式转换为指向第一个元素的指针。
  • C 中的 const 对象(不同于 C++)不一定是只读的。如果对对象有任何写保护,则留给实现。 const 只是程序员不写入对象的保证。编译器可以依赖这个合约。还有其他语言,常量和字面量之间没有实际区别。
  • @simplicisveritatis:如果它已经是一个指针,则不需要转换为指针。数组对象包含连续的元素序列。一个指针对象包含一个地址。它们是完全不同的东西。同样,请阅读comp.lang.c FAQ 的第 6 节;它比我有时间更详细地解释了这一点。
  • @simplicisveritatis:好的。这两句话现在清楚了吗?
【解决方案2】:

在你的情况下,答案是:

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

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

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

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

它是const 说明符和类型说明符的某种类型commutative property,在您的示例中为int

这里有几个例子来说明常量的用法:

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

和指向常量int的指针定义(指向的整数的值不能改变,但指针可以):

const int *p = &anInteger;  // constant data, non-constant pointer

【讨论】:

  • 从什么时候只能在运行时“创建”数组,在 C 中?如果将其定义为 const 值数组,则它将在编译时创建。
  • const 实体在编译时解析”。这是错误的。例如,const int r = rand(); 有效,但值是在运行时计算的
猜你喜欢
  • 1970-01-01
  • 2011-02-04
  • 1970-01-01
  • 1970-01-01
  • 2014-08-28
  • 1970-01-01
  • 2014-05-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多