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

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

4

4 回答 4

6

在 C90 和 C99 中,定义int array[i] = {0};是不合法的(不管你用 做什么i)。

在文件范围内声明的数组必须有一个整数常量表达式作为长度(分别为 6.5.4.2 或 6.7.5.2,§2)

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

  • 在 C90 中,不允许使用可变长度数组 (6.5.4.2)
  • 在 C99 中,不得初始化可变长度数组(6.7.8,§3)
于 2012-05-22T15:01:29.200 回答
4

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

编辑:在 C++ 中

于 2012-05-22T15:00:58.157 回答
4

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

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

于 2012-05-22T15:08:43.667 回答
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为 100 个元素的数组int。但是,您不能将初始化程序与 VLA 一起使用,int array[i] = {0};因此无效

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

更多来自 C99:

6.7.5.2 数组声明符
...
4 如果大小不存在,则数组类型是不完整类型。如果大小*不是表达式,则数组类型是未指定大小的变长数组类型,只能在具有函数原型范围的声明中使用;124)这样的数组仍然是完整的类型。如果大小是整数常量表达式,并且元素类型具有已知的常量大小,则数组类型不是变长数组类型;否则,数组类型是可变长度数组类型。
...
6.7.8 初始化
...
3 要初始化的实体的类型应为大小未知的数组或不是可变长度数组类型的对象类型。
124) 因此,* 只能用在不是定义的函数声明中(见 6.7.5.3)。
于 2012-05-22T15:43:58.643 回答