我有一个程序,在文件顶部定义了一些全局字符串,如下所示:
static const char * const STRING_A = "STRING A";
static const char * const STRING_B = "STRING B";
然后在主程序循环中我反复调用一个函数。此函数包含一个指针,该指针指向上述字符串,具体取决于用户输入。默认情况下我想将它设置为STRING_A,所以我基本上就是这样:
// Called repeatedly from a loop.
void input_function()
{
static const char *current = STRING_A;
// Do stuff and reassign different strings to "current"
...
}
我遇到的问题是,在编译时我得到“错误:初始化元素不是常数”。这是使用GCC 4.7.2。更让我困惑的是,如果我在输入函数中删除了“static”关键字,那么错误就会消失。这不是一个解决方案,因为函数需要static关键字来跟踪调用之间的当前字符串。
显然我可以通过多种方式解决这个问题,最简单的方法就是摆脱一些const限定符。但我想知道为什么这不起作用。
我目前的理解是全局字符串变量不能修改为指向不同的字符串,也不能修改它们的各个字符。 static关键字将它们保存在源文件的本地。
对于我的函数中的current
变量,我的理解是static关键字允许它在多次调用函数时保留其值,并且在这种情况下const限定符意味着{指向的字符串} {1}}可以更改 - 但不能更改它指向的字符串的字符。
我没有在这些语句中看到任何冲突,所以我不明白为什么编译器会出错 - 特别是为什么如果current
的“静态”说明符被删除它没有问题
谢谢,如果有人能解释这里的问题。
答案 0 :(得分:7)
6.7.8 / 4 [C99]:
具有静态存储持续时间的对象的初始值设定项中的所有表达式都应为常量表达式或字符串文字。
STRING_A
既不是,也就是错误。
解决这个问题的一个方法是:
void input_function()
{
static const char *current = NULL;
if (current == NULL) {
current = STRING_A;
}
...
}
答案 1 :(得分:3)
这是因为STRING_A
不是编译时常量。您的解释是正确的,但是您无法将常量初始化为非常量值(例如STRING_A
)。
编译器在编译时如何知道STRING_A
指向的内容?它没有 - STRING_A
将在每次执行程序时指向内存的只读部分中的不同地址,这取决于字符串文字在内存中的位置。
您需要执行以下操作来解决此约束,同时产生相同的效果:
// Defines current to be a null pointer.
static const char *current = NULL;
// Determine if current is a null pointer.
if ( current == NULL ) current = STRING_A;