将“static const char * const”赋值给“static const char *”

8

我有一个程序,在文件的顶部定义了一些全局字符串,就像这样:

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"
    ...
}

我遇到的问题是编译时出现“error: initializer element is not constant”的错误。这是使用GCC 4.7.2时出现的。更让我困惑的是,如果我在输入函数中去掉“static”关键字,该错误会消失。但这不是一个解决方案,因为需要静态关键字来跟踪当前字符串在调用之间的变化。
显然,我可以通过简单地去除一些常量限定符等方式来解决这个问题。但我想了解为什么它不能正常工作。
我的当前理解是全局字符串变量不能被修改以指向不同的字符串,它们的各个字符也不能被修改。静态关键字使它们保持在源文件的本地状态。
对于我的函数中的“current”变量,我理解静态关键字允许它在函数的多次调用之间保持其值,并且在这种情况下const限定符意味着由“current”指向的字符串可以更改,但无法更改指向的字符串的字符。
我没有看到这些语句之间的冲突,所以我不明白为什么编译器会出现错误 - 尤其是为什么如果去掉“current”的“static”关键字,它就没有问题。
感谢有人能解释一下这里的问题。
2个回答

7

6.7.8/4 [C99]:

静态存储期对象的初始化器中所有表达式都必须是常量表达式或字符串字面值。

STRING_A 都不是,因此出现了错误。

解决这个问题的一种方法是:

void input_function()
{
    static const char *current = NULL;
    if (current == NULL) {
        current = STRING_A;
    }

    ...
}

我还在琢磨中,但感谢您的快速回答。 - Adam Goodwin

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;

谢谢您的快速回答,不过我得把感谢送给 NPE,因为他似乎更快。再次感谢。 - Adam Goodwin

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