【问题标题】:Error initializer element is not constant错误初始值设定项元素不是常数
【发布时间】:2023-03-11 18:07:01
【问题描述】:

我的代码有问题,我无法解决....

报错的代码sn-p:

static FILE *debugOut = stderr;
static FILE *infoOut = stdout;

gcc 返回的错误是:

initializer element is not constant

【问题讨论】:

  • 您需要发布更多代码,因为这还不够,gcc 报告的内容还包括这些吗?还可以尝试在函数中分配它们(我认为您现在正在将其作为全局变量?)
  • 您正在初始化一个静态变量,这意味着编译器需要在编译时知道该值是什么。您正在尝试分配一个在编译时编译器不知道但在运行时知道的值 - 这就是它导致错误的原因。
  • 这不是重复的 - 它比链接的问题更具体 - 一个好的答案会详细说明为什么 stderr/stdout 在某些 c 库中是常量表达式 - 但不是全部 - 以及 C 标准不要求它们是常量表达式。然后添加上述代码的一些可移植变体。

标签: c


【解决方案1】:

尝试在 main 中执行,例如:

static FILE *debugOut;
static FILE *infoOut;

main(){
    debugOut = stderr;
    infoOut = stdout;


}

【讨论】:

    【解决方案2】:

    ANSI C 标准不要求 stderr/stdout 必须是常量表达式。

    因此,取决于使用的标准 C 库代码像这样

    static FILE *debugOut = stderr;
    

    编译或产生您询问的错误消息。

    例如,GNU C library definesstderr/stdout/stdin 作为非常量表达式。

    您基本上有两种选择来处理这种情况,即使此类代码可移植。

    从 main 初始化

    static FILE *debugOut = NULL;
    static FILE *infoOut  = NULL;
    
    int main(int argc, char **argv)
    {
      debugOut = stderr;
      infoOut  = stdout;
      // [..] 
      return 0;
    }
    

    从构造函数初始化

    在许多平台上,您可以将函数声明为构造函数,这意味着它在启动时在调用 main() 之前调用。例如,当使用GCC 时,您可以这样实现:

    static FILE *debugOut = NULL;
    static FILE *infoOut  = NULL;
    
    static void init_streams(void) __attribute__((constructor)); 
    static void init_streams(void)
    {
      debugOut = stderr;
      infoOut  = stdout;
    }
    

    这种constructor attribute 语法不是标准化的,但是由于 GCC 非常普遍并且其他编译器都在努力争取 GCC 兼容性,这实际上是非常可移植的。

    如果您需要将此代码移植到没有类似声明功能的其他编译器,您可以使用__GNU_LIBRARY__ 和/或__GNUC__ 等宏来保护此代码。

    【讨论】:

      【解决方案3】:

      来自 C99 标准:

      6.7.8 初始化

      约束

      4 具有静态存储持续时间的对象的初始化程序中的所有表达式应为常量表达式或字符串字面量。

      因此,

      static FILE *debugOut = stderr;
      static FILE *infoOut = stdout;
      

      如果编译器认为stderrstdout 不是常量表达式,则不是合法代码。

      这就是标准对stderrstdout 的规定。

      7.19 输入/输出<stdio.h>

      7.19.1 简介

      ...

         stderr
         stdin
         stdout
      

      它们是“指向FILE”类型的表达式,它们分别指向与标准错误、输入和输出流相关联的FILE 对象。

      解决方案

      处理此问题的标准兼容方法是将变量初始化为NULL,并将它们的值设置为main

      static FILE *debugOut = NULL;
      static FILE *infoOut  = NULL;
      
      int main()
      {
        debugOut = stderr;
        infoOut  = stdout;
      
        ...
      

      【讨论】:

      • @AndreasL。我最初的回答是指出问题。我添加了一个解决方案。
      • 谢谢。我正在迁移旧代码并且我没有主要方法,所以我在每个使用“文件”的方法中进行检查(if (file == NULL) { file = stdout; })。 “文件”可能已设置在其他位置...
      猜你喜欢
      • 2023-04-11
      • 1970-01-01
      • 1970-01-01
      • 2012-04-10
      • 2016-06-06
      • 1970-01-01
      • 2020-11-27
      • 1970-01-01
      相关资源
      最近更新 更多