字符串数组初始值设定项中的错误:初始值设定项元素不是常量

时间:2019-01-10 09:42:29

标签: c compile-time-constant

我需要定义一些字符串和一个用这些字符串初始化的数组,以供软件的不同部分使用。我想在这样的头文件中定义它们:

//.h file
const char *serviceStateKindNormal = "Normal";
const char *serviceStateKindUnmanned = "Unmanned";
const char *serviceStateKindScheduledMaintenanceDown = "ScheduledMaintenance (down)";
const char *serviceStateKindScheduledMaintenanceAvailable = "ScheduledMaintenance (available)";
const char *serviceStateKindMajorIncidentInProgress = "MajorIncidentInProgress";
const char *serviceStateKindPartialService = "PartialService";
const char *serviceStateKindOverloaded = "Overloaded";
const char *serviceStateKindGoingDown = "GoingDown";
const char *serviceStateKindDown = "Down";

const char *serviceStateKind[9] = {
    serviceStateKindNormal,
    serviceStateKindUnmanned,
    serviceStateKindScheduledMaintenanceDown,
    serviceStateKindScheduledMaintenanceAvailable,
    serviceStateKindMajorIncidentInProgress,
    serviceStateKindPartialService,
    serviceStateKindOverloaded,
    serviceStateKindGoingDown,
    serviceStateKindDown
};

但是编译器显示

error: initializer element is not constant
     serviceStateKindNormal

这里到底是什么问题,我必须选择哪些变量来定义变量?

2 个答案:

答案 0 :(得分:1)

在C语言中,常量是指文字常量,例如(3.142.718等)。 const限定的对象(任何类型)在C语言术语中不是常量。

要使用C语言术语创建常量,请使用#define伪指令,例如:

#define ServiceStateKindNormal "Normal"

答案 1 :(得分:0)

您在文件范围内声明的变量的所有初始化内容都必须是constant expression中的string literalinitialization。列表中有什么是常量表达式,变量值不在其中。所以:

 // there is an array of char[2]{'a',\0'} somewhere in the memory
 // we store the pointer value to that array inside the variable a
 static const char *a = "a";
 // now we want to statically initialize variable b with the same value
 static const char *b = a;

将不起作用,因为b是用指针a value 初始化的,该指针不是常量表达式。初始化具有静态存储持续时间的变量时,需要一个常量表达式。

你能做什么?以下:

  1. 一个好方法:为什么存储指向字符串文字"Normal"的指针?为什么不将数据本身存储在数组中?令人高兴的是,变量地址是一个常量表达式,因此我们可以在初始化中使用它!请注意,除了sizeof(serviceStateKindNormal)运算符结果之类的边角用法外,几乎所有用例和语义都保持不变。

    const char serviceStateKindNormal[] = "Normal";
    const char serviceStateKindUnmanned[] = "Unmanned";
    
    const char *serviceStateKind[] = {
        serviceStateKindNormal,
        serviceStateKindUnmanned,
    };
    
  2. 一种奇怪的方式:将指向指针的指针存储在数组内部的字符串中。由于变量地址是常量表达式,因此可以使用。请注意,使serviceStateKind成为三星级变量。您需要在使用时对数组进行双重解引用。 serviceStateKind是指向字符串的指针的指针数组。请注意,如何使用此类数组非常令人困惑,因此我建议您使用一个结构。

    const char *serviceStateKindNormal = "Normal";
    const char *serviceStateKindUnmanned = "Unmanned";
    
    const char **serviceStateKind[] = {
        &serviceStateKindNormal,
        &serviceStateKindUnmanned,
    };
    
    int main() {
        // question which one is correct?
        printf("%s\n", *serviceStateKind[1]);
        printf("%s\n", (*serviceStateKind)[1]);
        printf("%s\n", serviceStateKind[0][1]);
    }
    

但是由于我不认为自己是三星级的程序员,所以我会尝试使其至少达到两星级:

    const char *serviceStateKindNormal = "Normal";
    const char *serviceStateKindUnmanned = "Unmanned";

    struct {
        // points to a string
        const char **pnt;
    // an array of pointers to string
    } serviceStateKind[] = {
        &serviceStateKindNormal,
        &serviceStateKindUnmanned,
    };

    int main() {
        // more verbose
        printf("%s\n", *serviceStateKind[0].pnt);
    }
  1. 老式方式-宏。不要这样而且有什么不好的地方,您可以滥用字符串文字的预处理器串联,以将它们串联在一起。

    #define serviceStateKindNormal  "Normal"
    #define serviceStateKindUnmanned  "Unmanned"
    
    const char *serviceStateKind[] = {
        serviceStateKindNormal,
        serviceStateKindUnmanned,
    };
    
    int main() { 
       # magic
       printf(serviceStateKindNormal " " serviceStateKindUnmanned "\n");
    }
    
  

我认为是在这样的头文件中定义它们:

如果要在头文件中定义变量,则要用static进行标记,这样在链接到使用该{{ 1}}文件。将变量标记为.c也很好,以提示其他程序员它们有些不可更改。