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

我遇到的问题是,在编译时我得到“错误:初始化元素不是常量”。这是使用 GCC 4.7.2。更让我困惑的是,如果我去掉输入函数中的“静态”关键字,错误就会消失。但这不是一个解决方案,因为函数需要 static 关键字来跟踪调用之间的当前字符串。

显然,我可以通过多种方式解决这个问题,最简单的方法是去掉一些 const 限定符。但我想了解为什么这不起作用。

我目前的理解是全局字符串变量不能修改为指向不同的字符串,也不能修改它们的单个字符。static 关键字使它们保持在源文件的本地。

对于current我函数中的变量,我的理解是 static 关键字允许它在多次调用函数时保留其值,并且在这种情况下 const 限定符意味着指向的字符串current可以改变 - 但不是它指向的字符串。

我在这些语句中没有看到任何冲突,所以我不明白为什么编译器会给出错误 - 特别是为什么如果current删除了“静态”说明符就没有问题。

谢谢,如果有人可以解释这里的问题。

4

2 回答 2

7

6.7.8/4 [C99]:

具有静态存储持续时间的对象的初始化程序中的所有表达式都应为常量表达式或字符串文字。

STRING_A两者都不是,因此错误。

解决此问题的一种方法是遵循以下原则:

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

    ...
}
于 2013-08-10T15:52:50.500 回答
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;
于 2013-08-10T15:54:41.187 回答