为什么我会收到一个有关初始化程序不是常数的错误?

10

我正在使用以下代码。

const int X_ORIGIN = 1233086;             
const int Y_ORIGIN = -4728071;              
const int Z_ORIGIN = 4085704;
const int xyzOrigin[NUM_DIMENSIONS] = {X_ORIGIN, Y_ORIGIN, Z_ORIGIN};

当我编译它时,GCC 给了我以下错误。

Transformations.h:16:1: error: initializer element is not constant

这是什么意思?我该如何修复我的代码?


2
为什么不创建一个包含三个位置的结构体,而不是一个数组?这似乎有点违反直觉... - Nathan White
作为对@nathanwhite所说的附言,John Carmack说:https://twitter.com/ID_AA_Carmack/status/219884864185446402 - Michael Buen
相关:*C 中的文件作用域下可变数组*。 - Peter Mortensen
NUM_DIMENSIONS 在任何地方都没有定义,并且这个程序中没有第 16 行。它无法重现。 - Toby Speight
6个回答

21

通常人们会被关键字const的名称所误导,认为它表示一个不可改变的常量值。至少在C语言中,它的意思是只读。文件作用域下带有const限定符的对象没有足够的常数性质来作为数组初始化器。

举个例子证明非常数性质的存在,下面的声明是完全可以的:

 const volatile unsigned int milliseconds_since_boot;

该值是从编译器控制之外更新的(类似于硬件寄存器),并且您不允许对其进行赋值,即它是只读的。


4
为什么要点踩?如果有问题,请给我解决的机会。 - Jens
2
不是我的DV,但你可以更详细地阐述一下OP的实际问题。对于可能甚至不知道什么是“HW寄存器”的初学者来说,这个例子很难理解。 - too honest for this site

14

在 C 中,您不能在全局范围内这样做,只能在局部范围内,即在函数内部:

#define NUM_DIMENSIONS 3

const int X_ORIGIN = 1233086;             
const int Y_ORIGIN = -4728071;              
const int Z_ORIGIN = 4085704;

const int xyzOrigin[NUM_DIMENSIONS] = {X_ORIGIN, Y_ORIGIN, Z_ORIGIN}; // FAIL

void foo(void)
{
    const int xyzOrigin[NUM_DIMENSIONS] = {X_ORIGIN, Y_ORIGIN, Z_ORIGIN}; // OK
}

你也可以将代码编译为C++而不是C。


定义时使用define而不是const int非常重要。该死的大小似乎不能是任何类型的变量(甚至是常量)。 - MrMesees
仅适用于自动存储类,这意味着在函数内部,而不是静态的(或C11 _Thread_local)。 - dave_thompson_085

5

我不是一个正式的程序员,但我会这样做:

#define X_ORIGIN (1233086)
#define Y_ORIGIN (-4728071)
#define Z_ORIGIN (4085704)
const int xyzOrigin[NUM_DIMENSIONS] = {X_ORIGIN, Y_ORIGIN, Z_ORIGIN};

这样做只是一种文本替换。如果编译器仍然无法正常工作,那么你至少可以更接近于知道问题出在哪里。


4
@nathanwhite 能否详细说明一下?宏定义已经很好地解决了这个问题!(假设 NUM_DIMENSIONS 已经在其他地方定义了)。 - Jens
2
@nathanwhite 这些正是“初始化元素不是常量”错误的原因。将NUM_DIMENSIONS作为变量(无论是否有const限定符)会导致“文件范围内可变修改»xyzOrigin«”。 - Daniel Fischer
1
更好的做法是完全删除 NUM_DIMENSIONS,让数组大小自动调整为提供的元素数量。 - Alex Celeste

4

作为一种替代方案,在这种情况下,这也可以起作用:

enum { X_ORIGIN = 1233086,
       Y_ORIGIN = -4728071,
       Z_ORIGIN = 4085704 };

const int xyzOrigin[] = { X_ORIGIN, Y_ORIGIN, Z_ORIGIN };

int main()
{
    return 0;
}

2
在C语言中,具有静态存储期的对象必须使用常量表达式或包含常量表达式的聚合初始化器进行初始化。--AndreyT的答案 阅读后,您应该知道如果NUM_DIMENSIONS具有const限定符,则不是常量!然后您无法以这种方式初始化数组。
要使用此代码: const int xyzOrigin[NUM_DIMENSIONS] = {X_ORIGIN, Y_ORIGIN, Z_ORIGIN}; 您应该使用:#define NUM_DIMENSIONS 3 或者您可以只声明没有方括号内的任何变量const int xyzOrigin[] = {X_ORIGIN, Y_ORIGIN, Z_ORIGIN};

0

正如triclosan所说:

main()
{
    const int X_ORIGIN = 1233086;
    const int Y_ORIGIN = -4728071;
    const int Z_ORIGIN = 4085704;
    const int xyzOrigin[] = {X_ORIGIN, Y_ORIGIN, Z_ORIGIN};
}

这个很好用...

或者,如果你事先知道尺寸,可以使用以下代码:

#define DIM 3

main()
{
    const int X_ORIGIN = 1233086;
    const int Y_ORIGIN = -4728071;
    const int Z_ORIGIN = 4085704;
    const int xyzOrigin[DIM] = {X_ORIGIN, Y_ORIGIN, Z_ORIGIN};
}

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