使用C中的宏删除(或者有条件地附加)const修饰符



我在C中处理以下问题。我在代码中使用全局变量来定义一些全局参数。我希望这样的全局变量是常量,即使它们必须在从输入数据文件读取值的例程中初始化。简而言之,我正在寻找一种在C中初始化变量时"消除"常量的好方法(我想在C++中,由于const_cast,这不会是一个问题)

我想出了一个基于宏的模式来做到这一点,如下所示。它似乎很好用,但我有以下问题。有人在下面的程序中看到任何隐藏的缺陷或潜在的危险吗?有人会反对下面的方法而选择更简单的方法吗?

我的方法:

我有一个主头文件,其中包含我的全局变量(int N)的定义,就像一样

/* main_header.h */
#ifdef global_params_reader
#define __TYPE__QUAL__
#else
#define __TYPE__QUAL__ const
#endif
__TYPE__QUAL__ int          N;

我有一个实现N初始化的文件"get_global_params.c",它将N视为"int N"(因为它在定义global_params_reader后包括"main_header.h")

/* get_global_params.c */
#define global_params_reader
#include get_global_params.h
void get_global_params(char* filename){
    N = ... ; // calling some function that reads the value of N from 
              // the datafile "filename" and returns it
}

以及相应的头文件"get_global_params.h"

/* get_global_params.h */
#include "main_header.h"
void get_global_params(char* filename);

最后,我有一个main.c,它将N视为"const int N"(因为它包括"main_header.h"而没有定义global_params_reader):

/* main.c */
#include "main_header.h"
#include "get_global_params.h"
int main(int argc, char **argv){
    // setting up input data file //
    ...
   // initialize N //
   get_global_params(datafile);
   // do things with N //
   ...
}

我希望我的解释足够清楚。感谢您的反馈。

只需将全局变量包含在一个单独的文件中。

globl.h:

struct Globals{
  int N;
  //...
};
extern const struct Globals *const globals;

init_globl.h:

init_globals(/*Init Params*/);

globl.c

#include globl.h
#include init_globl.h
static struct Globals _globals;
const struct Globals *const globals = &_globals;
init_globals(/*Init Params*/){
  // Initialize _globals;
  //...
}

现在,您可以在启动时通过在任何需要访问该功能的文件中包含init_globl.h来初始化全局变量,其他人只需包含globl.h并使用符号globals->N就可以直接访问全局变量。

如果我是你,我会简单地避免这种全局变量。相反,我将用所有这些程序参数定义一个struct,并定义一个函数,该函数返回指向该struct(singleton模式)的唯一实例的const指针。这样,返回指针的函数可以非常量地访问singleton,而程序的整个其余部分则不能。这正是您所需要的,它干净且面向对象,因此没有理由乱用宏和强制转换。

实例可以声明为函数中的静态变量,也可以malloc‘ed为静态指针。这其实并不重要,因为这是该函数的实现细节,永远不会泄露给外部。代码的其余部分也不需要知道参数何时被实际读取,它只调用函数,并获得唯一一个具有所有有效参数的对象。

"我希望这样的全局变量是常量,即使它们必须在从输入数据文件读取值的例程中初始化。"

在运行时无法在c中初始化const。在c中,值有或没有const限定符,并且它是在声明时定义的。c不支持更改它。语义是固定的。但一些引用该标准的专家会更好、更可靠。

我认为这在c++中也不可能,但我不会打赌,因为c++可以在这里和那里发挥一些魔力。

最新更新