C99 指定初始化程序重复索引在构建输出或 lint 中根本没有标记

标签 c c99 lint designated-initializer

前几天我玩了一下指定的初始化程序,令我惊讶的是,多次使用同一个索引是有效的。更重要的是,当我这样做时,它甚至没有产生编译器警告、错误甚至信息性声明,甚至 PC-Lint 似乎也不在乎(我认为这最让我感到惊讶)。

我想知道在这种情况下编译器是否有原因甚至不提供信息消息,或者是否有额外的编译器/lint/等。可用于捕获或标记此问题的选项。

使用的工具:Renesas RX Standard Toolchain v1.2.0.0 (C99)、gcc 版本 4.4.3 (Ubuntu 4.4.3-4ubuntu5.1)(在 VM 中)、Lint-NT 9.00i

例如,我正在处理的一些旧代码 #defines 一堆命令,然后创建一个命令结构数组(此处大大简化)以循环查找和使用该特定命令:

#define CMD_RMEM 0
#define CMD_WMEM 1
#define CMD_XCRC 2
#define CMD_NULL 3

typedef struct
{
  const char  cmdID;
  const char* cmdStr;
} CMD;

const CMD commands[] = {
  {CMD_RMEM,"RMEM"},
  {CMD_WMEM,"WMEM"},
  {CMD_XCRC,"XCRC"},
  {CMD_NULL,"NULL"},
};

然后我想起了我在某处看到的指定初始化语法,并认为除了检测重复的命令索引之外,它还可以为数组中项目的排列提供更大的灵 active ,例如:
//(same #def's & typedef as above)
const CMD commands[] = {
  [CMD_RMEM] = {CMD_RMEM,"RMEM"},
  [CMD_NULL] = {CMD_NULL,"NULL"}, //different order in ititializer list,
    // but designation keeps it in the same array/memory position, so
    // this will still be the 'last' element
  [CMD_CMEM] = {CMD_CMEM,"CMEM"},
  [CMD_WMEM] = {CMD_WMEM,"WMEM"},
  [CMD_XCRC] = {CMD_XCRC,"XCRC"},
};

会产生与上面的初始代码相同的效果,但可以灵活地安排数组声明中的项目(它确实如此)和(我在想/希望)
#define CMD_RMEM 0
#define CMD_WMEM 1
#define CMD_XCRC 1 // obvious dupe in a short list, but not so obvious
  // if part of a much longer list or if split among multiple files
#define CMD_NULL 2

// (Same designated initializer section as above)

至少会产生一个警告,因为我们不止一次使用相同的指定索引(它 )(这个例子很容易通过添加命令而不移动最后一个 NULL 占位符)。

GCC Designated Inits页面注释了一个 GNU 扩展,它允许您在初始化程序中使用范围,我可以看到它对定义整个范围然后覆盖某些部分的能力很有用(例如 int arr[] = {[0 ... 99] = -1, [42] = 1} ,但我不明白为什么它仍然不是至少在某种程度上被标记...

在同一个 GCC 页面的更下方,它确实解决了多个字段的主题,但没有解释它为什么会这样:“如果同一个字段被多次初始化,它具有上次初始化的值。如果有的话这种重写的初始化有副作用,不确定是否发生副作用。目前,GCC 会丢弃它们并发出警告。

This IBM page也展示了一个有趣的例子,但仍然没有回答(至少对我来说)为什么它至少不是某种构建消息......

最后,这个 gcc patch page从 2000 年 12 月开始,表明重复检查已被明确删除,但没有(根据我简要阅读的内容)解释原因。

那么,为什么这(似乎)被掩盖了?有没有办法让编译器(甚至 lint)标记这个(以提供更多安全性)(在 c/c99 中;不要只说“使用 c++”或其他东西:p)?

最佳答案

我没有解释为什么——也许仅仅是因为指定的初始化器仍然是新的并且很少使用。编译器制造商必须考虑将从新功能中受益的程序员数量。

Clang 警告您的构造:

$ clang  -std=c99 -Wall -c t.c
t.c:24:17: warning: initializer overrides prior initialization of this subobject [-Winitializer-overrides]
  [CMD_XCRC] = {CMD_XCRC,"XCRC"},
                ^~~~~~~~
t.c:4:18: note: expanded from macro 'CMD_XCRC'
#define CMD_XCRC 1 // obvious dupe in a short list, but not so obvious
                 ^
t.c:23:17: note: previous initialization is here
  [CMD_WMEM] = {CMD_WMEM,"WMEM"},
                ^~~~~~~~
t.c:2:18: note: expanded from macro 'CMD_WMEM'
#define CMD_WMEM 1
                 ^

(我必须对其进行一些小改动才能编译,但你明白了。)
$ clang -v
Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
Target: x86_64-apple-darwin12.3.0
Thread model: posix

关于C99 指定初始化程序重复索引在构建输出或 lint 中根本没有标记,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16742467/

相关文章:

android - module-info.class 的 lint 分析期间出现意外故障

我可以将处理器缓存内容显式转储到文件吗?

c - 是否可以将 C 源代码编译成 R,以便生成的 R 函数与平台无关?

c++ - 通过结构指针将结构的成员初始化为零

c - 发生错误时,scanf 返回 1 而不是 0

c++ - 我如何告诉 lint 跟踪指向 vector 的保管指针?

c - 为什么递归函数在达到峰值后会向下计数?

c - 为什么 int x[n] 错误,其中 n 是一个 const 值?

c++ - extern "C"静态数组函数参数

Android Studio lint.xml 配置