警告:初始化元素在加载时不可计算

warning: initializer element is not computable at load time

我无法理解 gcc -pedantic 在以下情况下的输出:

$ gcc -pedantic parse.c -lpopt
parse.c: In function ‘main’:
parse.c:19:7: warning: initializer element is not computable at load time
       { "bps", 'b', POPT_ARG_INT, &speed, 0,
       ^
parse.c:20:7: warning: initializer element is not computable at load time
       "signaling rate in bits-per-second", "BPS" },
       ^
parse.c:27:7: warning: initializer element is not computable at load time
       { "raw", 'r', 0, &raw, 0,
       ^
parse.c:28:7: warning: initializer element is not computable at load time
       "don't perform any character conversions" },
       ^

使用以下 C 代码(取自 here):

$ cat parse.c
#include <popt.h>

int main(int argc, const char *argv[]) {
  char    c;            /* used for argument parsing */
  int     speed = 0;    /* used in argument parsing to set speed */
  int     raw = 0;      /* raw mode? */
  struct poptOption optionsTable[] = {
      { "bps", 'b', POPT_ARG_INT, &speed, 0,
      "signaling rate in bits-per-second", "BPS" },
      { "crnl", 'c', 0, 0, 'c',
      "expand cr characters to cr/lf sequences" },
      { "hwflow", 'h', 0, 0, 'h',
      "use hardware (RTS/CTS) flow control" },
      { "noflow", 'n', 0, 0, 'n',
      "use no flow control" },
      { "raw", 'r', 0, &raw, 0,
      "don't perform any character conversions" },
      { "swflow", 's', 0, 0, 's',
      "use software (XON/XOF) flow control" } ,
      POPT_AUTOHELP
        { NULL, 0, 0, NULL, 0 }
  };
}

使用 -ansi-std=c89 可以编译完全相同的代码。为什么 -pedantic 选项失败了?

使用:

$ gcc --version
gcc (Debian 4.9.1-19) 4.9.1
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ apt-cache policy libpopt-dev
libpopt-dev:
  Installed: 1.16-10
  Candidate: 1.16-10
  Version table:
 *** 1.16-10 0
        500 http://ftp.fr.debian.org/debian/ jessie/main amd64 Packages
        100 /var/lib/dpkg/status

C89标准中,初始化列表必须是编译时常量表达式,因此会出现警告。但是在 C99 中它是受支持的。

C89中,您可以:

struct poptOption optionsTable[2];

optionsTable[0] = {"bps", 'b', POPT_ARG_INT, &speed, 0,
  "signaling rate in bits-per-second", "BPS" };
optionsTable[1] = {"crnl", 'c', 0, 0, 'c',
  "expand cr characters to cr/lf sequences" };

因为变量速度是在栈上分配的,它的地址在编译时是未知的。只有当 main() 正在执行时,它的地址才会被知道。变量 raw 也一样。与任何优秀的编译器一样,您的编译器的错误消息不会准确指向错误的元素,并且让您头疼地理解它在抱怨什么。