FILE * .. = stdout:错误初始化元素不是常量

时间:2016-02-24 07:51:26

标签: c linux suse

我的C代码如下:

[Linux:/si/usr/hrl]vi test.c    

#include <stdio.h>

FILE * hw = stdout;

int main(void)
{
        return 0;
}

当我在SUSE上编译时,会出现如下错误:

[Linux:/si/usr/hrl]cc test.c -o test
test.c:3: error: initializer element is not constant

我查看了头文件stdio.h,发现stdout似乎已被定义为常量。那么为什么错误会产生?顺便说一句,我在AIX上编译相同的代码,这是成功的结果。

1 个答案:

答案 0 :(得分:4)

该标准不要求stdinstdoutstderr为常量。

C99的n1256草案在7.19.1中输入/输出&lt; stdio.h&gt;

  

标题声明......
  ...
  TMP_MAX
  扩展为整数常量表达式 ...

     

stderr的   标准输入   标准输出
  其中表达式类型''指向FILE的指针''...

(强调我的)

明确指出,其他一些值是不变的,而stdinstdoutstderr

则没有任何说明

所以你必须在main中放置初始化:

#include <stdio.h>

FILE * hw;

int main(void)
{
        hw = stdout;
        ...
        return 0;
}

在AIX标准库中,stdout恰好是一个常量,但它只是一个实现细节,你不能依赖它,因为它可能会破坏任何更新的版本。

但你不应该依赖stdout作为变量(甚至是左值),因为它也是GCC库中的实现细节。

如果您无法更改大部分代码,只需要GCC hack来使其可编译,您可以尝试使用gcc 构造函数属性扩展名。

摘自gcc documentation

  

6.31声明函数的属性

     

在GNU C中,您声明了程序中调用的某些函数,这些函数可以帮助编译器优化函数调用并更仔细地检查代码。

     

关键字__attribute__允许您在进行声明时指定特殊属性。此关键字后面是双括号内的属性规范。目前为所有目标上的函数定义了以下属性:...,构造函数,...
  ...
  构造函数属性导致在执行main()...

之前自动调用该函数

所以你可以使用:

#include <stdio.h>

FILE * hw;

void initHw(void) __attribute__((constructor)) {
    hw = stdout;
}

int main(void)
{
        return 0;
}

请注意:它是gcc扩展名,意味着您的代码正确C。