最近我很失望地了解到C不允许在静态变量初始化期间分配变量,这与C ++不同。例如。以下代码编译为C ++ ...
#include <stdio.h>
int foo()
{
return 1;
}
static int g_i = foo();
int main( int argc, char* argv[] )
{
printf( "%d\n", g_i );
return 0;
}
...但是使用C编译器发出以下错误:
>cc -g main.c
main.c:8:1: error: initializer element is not constant
static int g_i = foo();
^
我认为通过使用逗号运算符a-la:
可以很聪明static int g_i = ( foo(), 1 );
...但编译器似乎对我的聪明才智并不感兴趣,并且输出有效的错误:
>cc -c main.c
main.c:8:1: error: initializer element is not constant
static int g_i = ( foo(), 1 );
^
:(
问:为什么使用逗号运算符不起作用?我可能没有意识到一些微妙之处,但我的理解使我认为它应该有效:C
编译器要求g_i
被初始化为编译时常量;据说逗号运算符会给我评估逗号左边的代码,但是为逗号分配代码,这是一个编译时常量。
问:是否有任何黑客攻击 - 我不在乎有多脏 - 这样可以将g_i
的返回值分配给foo()
g_i
?
这是C
程序的简化表示,我真的只想在main()
之前调用一个函数 - 我不关心返回值,但调用它是一个更复杂的问题在void
之前的main()
函数,我宁愿通过使用int
函数完全回避它,该函数的值被分配给一次性static int
变量。
答案 0 :(得分:8)
C不支持动态初始化。因此,需要使用常量表达式初始化静态对象。不允许常量表达式涉及任何运行时计算,即使这些计算不影响表达式的最终值。使用逗号运算符的表达式不是常量表达式。
(此外,即使你不从它们调用任何函数,C语言常量表达式也禁止使用逗号运算符。例如,即使像(1, 2, 3)
那样微不足道的东西也不是常量表达式。)
C中的所有静态对象必须在编译时初始化,至少在概念上是这样。在这种情况下,“概念上”一词指的是,地址常量表达式实际上可以在很晚的时候进行评估,即使在加载时也是如此。但问题是,一旦程序开始运行任何用户级代码,所有静态对象都必须已经知道预先评估的值,就像它们在编译时被初始化一样。出于这个原因,C(与C ++相对)没有/不需要静态对象的初始化顺序的概念,并且不可能受SIOF的影响。
因此,在标准C中无法解决此限制。您将无法使用在运行时运行代码(或以任何方式涉及)运行代码的方式初始化静态对象。您的实现可能提供特定于实现的功能,可能会执行类似的操作,但这超出了C语言本身的范围。