不使用字符串时,Initializer Element不是常量错误

时间:2017-04-06 16:34:10

标签: c

我正在对Doom的源代码进行一些实验。我对C不是很熟悉,但我还是给它一个机会。我试图修改的代码如下所示:

{"sndserver", (int *) &sndserver_filename, (int) "sndserver"},

而我正试图这样做(删除在多个地方硬编码相同的位置):

{"sndserver", (int *) &sndserver_filename, (int) sndserver_filename},

但它给了我标题中的错误。我尝试在同一位置声明另一个变量sndserver_filename源于那里的转换,但是一旦我尝试在这里使用它我就会得到同样的错误。

是否有理由将字符串转换为int,但该变量不会出现,并且有解决方法吗?

上下文:

#ifdef SNDSERV
extern char*    sndserver_filename; // value is "./sndserver"
extern int  mb_used;
#endif

结构声明和初始化

typedef struct
{
    char*   name;
    int*    location;
    int     defaultvalue;
    int     scantranslate;      // PC scan code hack
    int     untranslated;       // lousy hack
} default_t;

default_t   defaults[] =
{
    {"mouse_sensitivity",&mouseSensitivity, 5},
    {"sfx_volume",&snd_SfxVolume, 8},
    {"music_volume",&snd_MusicVolume, 8},
    {"show_messages",&showMessages, 1},


#ifdef NORMALUNIX
    {"key_right",&key_right, KEY_RIGHTARROW},
    {"key_left",&key_left, KEY_LEFTARROW},
    {"key_up",&key_up, KEY_UPARROW},
    {"key_down",&key_down, KEY_DOWNARROW},
    {"key_strafeleft",&key_strafeleft, ','},
    {"key_straferight",&key_straferight, '.'},

    {"key_fire",&key_fire, KEY_RCTRL},
    {"key_use",&key_use, ' '},
    {"key_strafe",&key_strafe, KEY_RALT},
    {"key_speed",&key_speed, KEY_RSHIFT},

// UNIX hack, to be removed. 
#ifdef SNDSERV
    {"sndserver", (int *) &sndserver_filename, (int) "sndserver"},
    {"mb_used", &mb_used, 2},
#endif

#endif

#ifdef LINUX
    {"mousedev", (int*)&mousedev, (int)"/dev/ttyS0"},
    {"mousetype", (int*)&mousetype, (int)"microsoft"},
#endif

    {"use_mouse",&usemouse, 1},
    {"mouseb_fire",&mousebfire,0},
    {"mouseb_strafe",&mousebstrafe,1},
    {"mouseb_forward",&mousebforward,2},

    {"use_joystick",&usejoystick, 0},
    {"joyb_fire",&joybfire,0},
    {"joyb_strafe",&joybstrafe,1},
    {"joyb_use",&joybuse,3},
    {"joyb_speed",&joybspeed,2},

    {"screenblocks",&screenblocks, 9},
    {"detaillevel",&detailLevel, 0},

    {"snd_channels",&numChannels, 3},



    {"usegamma",&usegamma, 0},

    {"chatmacro0", (int *) &chat_macros[0], (int) HUSTR_CHATMACRO0 },
    {"chatmacro1", (int *) &chat_macros[1], (int) HUSTR_CHATMACRO1 },
    {"chatmacro2", (int *) &chat_macros[2], (int) HUSTR_CHATMACRO2 },
    {"chatmacro3", (int *) &chat_macros[3], (int) HUSTR_CHATMACRO3 },
    {"chatmacro4", (int *) &chat_macros[4], (int) HUSTR_CHATMACRO4 },
    {"chatmacro5", (int *) &chat_macros[5], (int) HUSTR_CHATMACRO5 },
    {"chatmacro6", (int *) &chat_macros[6], (int) HUSTR_CHATMACRO6 },
    {"chatmacro7", (int *) &chat_macros[7], (int) HUSTR_CHATMACRO7 },
    {"chatmacro8", (int *) &chat_macros[8], (int) HUSTR_CHATMACRO8 },
    {"chatmacro9", (int *) &chat_macros[9], (int) HUSTR_CHATMACRO9 }

};

2 个答案:

答案 0 :(得分:0)

What your compiler said: the initializer element is not a constant expression. An address like &sndserver_filename is a constant expression (the linker fills in the symbol's value), but a pointer variable may hold any address--the actual value may depend on the flow of the program, so it can't be used to initialize anything.

From C11 6.7.9 Initialization:

4 All the expressions in an initializer for an object that has static or thread storage duration shall be constant expressions or string literals.

That's a constraint and compilers are required to diagnose violations of constraints.

答案 1 :(得分:0)

让我试着提供一个解释。

你宣布

extern char*    sndserver_filename;

然后在需要编译时地址(确实是链接时间)的上下文中使用sndserver_filename

但是sndserver_filename的值在编译时是未知的。在程序开始时它是NULL。稍后您可以分配给它:

sndserver_filename = "aaa";

再次分配:

sndserver_filename = "bbb";

这对编译时初始化没有用。

你真正需要的是静态分配的数组,而不是指针:

extern char sndserver_filename[];

注意方括号。

这告诉编译器有一个静态分配的字符数组(此时不知道数组的大小)。

在其中一个C文件中,在全局范围内,您需要执行以下操作:

char sndserver_filename [256];

实际分配内存(并指定大小)。

然后你可以使用sndserver_filename作为静态初始化程序,你可以使用strcpy设置它的值(确实,strncpy以确保你不会复制过去的数组大小):

strcpy(sndserver_filename, "bbb");

请注意

sndserver_filename = "aaa";

现在是编译时错误。