使用具有存储的常量变量分配数组

时间:2012-05-22 14:53:12

标签: c++ c

const int i = 100;
int *j = &i;
int array[i] = {0};

这合法吗?我读到某个地方没有& i,i和100将被添加到符号表中,但由于& i,存储被强制为i,100将在编译时存储在i中;因此,编译器将无法读取i(来自存储)的值来分配数组 - 这是真的吗?

4 个答案:

答案 0 :(得分:6)

在C90和C99中,定义int array[i] = {0};不合法(无论您使用i做什么)。

在文件范围声明的数组必须有一个整数常量表达式作为length(6.5.4.2或6.7.5.2,§2,resp。)

如果定义具有功能/块范围,则它仍然是非法的,因为

  • 在C90中,不允许使用可变长度数组(6.5.4.2)
  • 在C99中,不得初始化可变长度数组(6.7.8,§3)

答案 1 :(得分:4)

int *j = &i;应为const int *j = &i;。在那之后,您的代码是合法的。

编辑:在C ++中

答案 2 :(得分:4)

绝对没有理由为什么变量不能同时具有编译时常量值物理存储。因此,它取决于语言的标准。

C ++允许常量整数为编译时常量。 C没有。一些编译C的C ++编译器将混合并匹配两种语言的某些功能,因此编译器可能会接受它作为标准的扩展。

答案 3 :(得分:1)

  

这合法吗?我读到某个地方没有& i,i和100将被添加到符号表中,但由于& i,存储被强制为i,100将在编译时存储在i中;因此,编译器将无法读取i(来自存储)的值来分配数组 - 这是真的吗?

以下是C99标准的语言:

6.7.3类型限定符
...
3与限定类型关联的属性仅对表达式有意义 是左值。 114)
114)实现可能会将const对象放在volatile的只读区域中 存储。此外,如果其地址是,则实现不需要为这样的对象分配存储 从未使用过。

所以,有点真实,但在这种情况下并不真正相关。编译器不 i创建存储以在其他地方使用其值;它可以简单地使用值为100的立即操作数代替i。无论哪种方式,行int j = &i;都是不必要的。

i不是整数常量表达式,这意味着它不是编译时常量(在C中; C ++在这方面是不同的);它是一个运行时变量,其值在其生命周期内可能不会被修改。

从C99开始,您可以使用运行时变量指定数组大小,即使是一个声明为const的变量,所以

const int i = 100;
int array[i];

array分配为int的100个元素数组。但是,您无法将初始化程序与VLA一起使用,因此int array[i] = {0}; 有效。

同样,C ++是不同的,根本不支持VLA。但是由于i被声明为const,C ++将其视为编译时常量,这意味着您的代码应该是合法的C ++(无论如何它都是为我构建的)。

更多来自C99:

6.7.5.2数组声明符
...
4如果大小不存在,则数组类型为不完整类型。如果大小为*而不是。{ 作为表达式,数组类型是未指定大小的可变长度数组类型, 它只能用于具有函数原型范围的声明; 124)这样的数组是 尽管如此,完整的类型。如果size是一个整型常量表达式,并且元素类型具有已知的常量大小,则数组类型不是可变长度数组类型; 否则,数组类型是可变长度数组类型 ...
6.7.8初始化
...
3要初始化的实体的类型应为未知大小的数组或对象类型 这不是可变长度数组类型。
124)因此,*只能用于非定义的函数声明(见6.7.5.3)。