错误:初始化元素不是初始化已知大小的结构的编译时常量,这是C

时间:2017-08-07 15:24:03

标签: c

这是C,(lex驱动程序代码),直接来自Schreiner和Friedman编译器的第33页,只需键入它就会抛出错误:

  

"错误:初始化元素不是编译时常量。

根据K& R第124页结构数组初始化检查并使用不同名称的相同位代码。它清楚地表明在编译时已知这个IS的大小。这是gcc的问题吗? 我正在编译命令行:lex samplec.l;然后,cc -DDEBUG lex.yy.c -ll -o lexc; 此时它会抛出错误。 OBB

%{
/*
**
**  samplec.l -- lexical analysia
**
*/

#ifdef      DEBUG

#  include <assert.h>

  main ()
    {
     char * p;

     assert(sizeof(int) >= sizeof(char *));

     while (p = (char *) yylex())
       printf("%-10.10s is \"%s\"\n",p, yytext);
  }

  s_lookup() {}

  int yyerrs = 0;

#   define token(x) (int) "x"

#else ! DEBUG

#   define "y.tab.h"
#   define token(x) x

#endif DEBUG

#define END(v) (v-1 + sizeof v / sizeof v[0])
static int screen();
%}

letter                      [a-zA-Z]
digit                       [0-9]
letter_or_digit             [a-zA-Z0-9]
white_space         [ \t\n]
blank                       [ \t]
other                       .

%%

^"#"{blank}*{digit}+({blank}+.*)?\n yymark();

">="                    return token(GE);
"<="                        return token(LE);
"=="                        return token(EQ);
"!="                        return token(NE);
"+="                        return token(PE);
"-="                        return token(ME);
"*="                        return token(TE);
"/="                        return token(DE);
"%="                        return token(RE);
"++"                        return token(PP);
"--"                        return token(MM);

{letter}{letter_or_digit} return screen();

{digit}+            { s_lookup(token(Constant));
                          return token(Constant);
                    }

{white_space}*              ;

{other}                     return token(yytext[0]);

%%

/*
**
**  reserve word screening
**
*/

static struct rwtable {
    char *rw_name;
    int rw_yylex;
   } rwtable[] ={
   "break", token(BREAK),
   "continue", token(CONTINUE),
   "else", token(ELSE),
   "if", token(IF),
   "int", token(INT),
   "return", token(RETURN),
   "while", token(WHILE)
   };

static int screen()
   {
    struct rwtable * low = rwtable,
            * high = END(rwtable),
            * mid;

    int c;

    while (low <= high)
      {
       mid = low + (high-low)/2;
       if ((c = strcmp(mid->rw_name, yytext)) == 0)
            return mid->rw_yylex;
       else if (c < 0)
            low = mid+1;
       else
            high = mid-1;
     }
     s_lookup(token(Identifier));
     return token(Identifier);
}

3 个答案:

答案 0 :(得分:1)

D 编译器构建与Unix的简介一书。 Friedman Schreiner,H。George Friedman Jr。非常过时(1985):现代编译器不再使用C语言。

token的定义使用过时的字符串形式:

#define token(x) (int) "x"

很久以前,在ANSI-C之前已经弃用了它。

您可以尝试将此定义更改为

#define token(x) #x

但是代码依赖于当前系统可能会失败的其他一些假设:

  • sizeof(int) >= sizeof(char*) - &gt;在大多数当前的64位系统上并非如此

我建议你寻找一个关于编译器构建的最新教程:你可以在网上找到很多很好的参考资料,还有很多开源软件。

答案 1 :(得分:0)

问题是指针被强制转换为int。您的指针很可能是64位,但int只有32位。链接器无法表示截断的指针,因此这些值不是编译时常量。此外,如果编译器能够表示这些截断的指针,当您尝试将int转换回指针时,您会得到一个令人讨厌的惊喜,因为它可能无法正确恢复丢失的32位。

某些平台提供类型intptr_tuintptr_t,它们是有符号和无符号整数类型,保证宽度足以允许在不丢失的情况下进行指针类型的转换。当然,这对这里没有帮助,因为lex想要一个普通的int

答案 2 :(得分:0)

发生错误是因为静态存储持续时间的对象的初始值设定项必须是常量;并根据C11 6.6p6

  

整数常量表达式应具有整数类型,并且具有整数常量的操作数,枚举常量,字符常量,结果为整数常量的sizeof表达式,_Alignof表达式和浮动常量,它们是强制转换的直接操作数。 整数常量表达式中的转换运算符只能将算术类型转换为整数类型,除非作为sizeof或_Alignof运算符的操作数的一部分。

"x"的类型为char *,指针不是算术类型,因此转换为整数的指针不能是整数常量表达式。