C 如果缺少常量字符*数组初始化逗号,则生成编译器警告

C 如果缺少常量字符*数组初始化逗号,则生成编译器警告,c,initialization,C,Initialization,我在C代码中经常使用字符串文字表。这些表格大致如下所示: static const char* const stateNames[STATE_AMOUNT] = { "Init state", "Run state", "Pause state", "Error state", }; 上面代码的问题是,如果表变长并且在开发过程中被修改,我会不时忘记一个逗号。代码编译时没有逗号丢失的问题,但最后一个字符串设置为NULL,我的程序最终崩溃。我使用MinGW和Keil

我在C代码中经常使用字符串文字表。这些表格大致如下所示:

static const char* const stateNames[STATE_AMOUNT] =
{
    "Init state",
    "Run state",
    "Pause state",
    "Error state",
};
上面代码的问题是,如果表变长并且在开发过程中被修改,我会不时忘记一个逗号。代码编译时没有逗号丢失的问题,但最后一个字符串设置为
NULL
,我的程序最终崩溃。我使用MinGW和Keil编译器进行验证


如果逗号丢失,有没有办法为我的初始化生成编译器警告?

将每个
const char*
括在一对括号中应该可以解决问题,如以下代码段所示:

static const char* const stateNames[5] =
{
    ("Init state"),
    ("Run state"),
    ("Pause state")     //comma missing
    ("Pause state3"),
    ("Error state")
};
如果您忘记了逗号,您将得到一个编译错误,类似于:
error:called object不是函数或函数指针


请注意,如果您忘记了逗号,实际发生的情况是C将实际连接两个(或更多)字符串,直到下一个逗号或数组结束。例如,假设您忘记了逗号,如下所示:

static const char* const stateNames[] =
{
    "Init state",
    "Run state",
    "Pause state" //comma missing
    "Pause state3" //comma missing
    "Error state"
};

int main(void)
{  
    printf("%s\n", stateNames[0]);
    return 0;    
}
这就是(其他编译器生成类似代码):


很明显,最后三个字符串是串联的,数组的长度不是预期的长度。

如果出现意外结果,可以让编译器对数组进行计数并生成错误消息:

enum { STATE_AMOUNT = 4 };

static const char* const stateNames[] =
{
    "Init state",
    "Run state",
    "Pause state"    // <--- missing comma
    "Error state",
};

_Static_assert( sizeof stateNames / sizeof *stateNames == STATE_AMOUNT,
        "oops, missed a comma" );
enum{STATE_AMOUNT=4};
静态常量char*常量stateNames[]=
{
“初始状态”,
“运行状态”,

“Pause state”//这并没有让编译器来帮助您,但我发现像下面这样编写它会让人更容易不删除逗号:

static const char* const stateNames[STATE_AMOUNT] =
{
      "Init state"
    , "Run state"
    , "Pause state"
    , "Error state"
};

我总是使用对显式大小数组的引用来解决这个问题

// no explicit size here
static const char* const stateNames[] =
{
    "Init state",
    "Run state",
    "Pause state",
    "Error state",
};
static const char* const (&stateNameVerifier)[STATE_AMOUNT] = stateNames;


如果您只是忘记将状态添加到此表中,会发生什么情况?@Jeroen3 true这会导致相同的错误。使用静态断言根据状态量测试列表长度也可以解决此问题。静态断言似乎是一个更优雅的解决方案。我想您在执行静态断言之前就养成了这样做的习惯作为语言的一部分添加了ments?你现在还看到它比验证数组预期大小的静态断言有什么优势吗?@CodyGray:是的,这是预静态断言,因为你提到了它,在结尾添加一些东西也更容易。你不必编辑前一行来添加逗号。(缺少逗号的主要原因。)@datafiddler:同意。当您对SQL SELECT命令中的列进行注释和取消注释时,它对于微调这些列的列表也很有用。您经常想要更改最后一个列,而很少想要更改第一个列。这样您就不必修改多行来注释一个项。该死……这正是我刚才想要的答案打字!
// no explicit size here
static const char* const stateNames[] =
{
    "Init state",
    "Run state",
    "Pause state",
    "Error state",
};
static const char* const (&stateNameVerifier)[STATE_AMOUNT] = stateNames;
main.cpp:10:32: error: reference to type 'const char *const [5]' could not bind to an lvalue of type 'const char *const [4]'
static const char* const (&stateNameVerifier)[STATE_AMOUNT] = stateNames;