使用非恒定值初始化静态变量

时间:2014-11-03 15:07:30

标签: c macros

从21世纪的C书:

  

初始化静态变量,即使是函数内部的变量   当程序启动时,在main之前,所以你无法初始化它们   具有非常数值。

//this fails: can't call gsl_vector_alloc() before main() starts
static gsl_vector *scratch = gsl_vector_alloc(20);
     

这是一个烦恼,但很容易用宏来解决从零开始   并在首次使用时分配:

#define Staticdef(type, var, initialization) \ 
static type var = 0; \
if (!(var)) var = (initialization);

//usage:
Staticdef(gsl_vector*, scratch, gsl_vector_alloc(20));

我不明白宏的差异。预处理后,它是否完全相同?


2 个答案:

答案 0 :(得分:7)

  

预处理后是不是完全一样?

不,两者都不一定表现相同。

此启动保证运行一次

static int i = 42; /* Initialisation */

此作业

static int i = 0;
if (!i) /* line X */
  i = 42; /* Assignment */

不是,因为每次,程序流程达到第X行,i等于0,然后将i 设置为到{ {1}}(再次)。

示例:

42

运行它并查看差异:

#include <stdio.h>

void foo(int inew)
{
  static int i = 42;

  printf("%d\n", i);

  i = inew;
}

void bar(int inew)
{
  static int i = 0;
  if (!i)
    i = 42;

  printf("%d\n", i);

  i = inew;
}

int main(void)
{
  foo(43);
  foo(0);
  foo(44);

  printf("\n");

  bar(43);
  bar(0);
  bar(44);

  return 0;
}

答案 1 :(得分:3)

预处理器只替换文本,因此Staticdef宏的最终结果是:

static gsl_vector *scratch = 0 ;
if (!(scratch )) scratch = (gsl_vector_alloc(20));

如果您愿意或可以使用宏,可以自行输入。

这当然与不正确的版本不同:

static gsl_vector *scratch = gsl_vector_alloc(20);

我建议不使用宏,因为它不能包含在do {}中,只会混淆代码。