【问题标题】:Why do we use pre processor directives to define variables?为什么我们使用预处理器指令来定义变量?
【发布时间】:2014-12-30 10:00:47
【问题描述】:

我有一段这样的代码:

/* T matrix */
#define T11     0
#define T12_re  1
#define T12_im  2

int main(int argc, char *argv[])
{
    return 1;
}

我的问题是为什么它使用预处理器指令来定义全局变量,而不是简单地使用这样的代码:

/* T matrix */
double T11 = 0;
double T12_re = 1;
double T12_im = 2;

int main(int argc, char *argv[])
{
    return 1;
}

【问题讨论】:

  • 这很可能来自 C 代码。

标签: c++ variables global-variables c-preprocessor preprocessor-directive


【解决方案1】:

预处理器符号是不是变量。在您的第一个代码中,T13_im(等等...)不是一个变量(而是一个经过预处理的名称,在解析时扩展为 4

在你的第二个代码中(它不会像你写的那样编译),你可能有

const double  T12_re=  1.0;

那么你已经声明了一个const double 类型的变量T12_re

阅读C preprocessor 上的wikipage,GNU cpp 的文档,并意识到编译器只能看到预处理的形式;对于您的文件yoursource.cc,您可以使用命令
g++ -Wall -C -E yoursource.cc > yoursource.ii 获得预处理的表单yoursource.ii,然后使用寻呼机或编辑器查看生成的yoursource.ii

有时,预处理器允许使用this 之类的可爱技巧。而且你不能总是使用变量。例如,case 表达式应该是编译时常量,并且不能在 C 中是 const int 变量。 (你可以使用一些enum,它在C和C++中是不同的)。

【讨论】:

  • 是的,它是一个宏,但我们为什么要使用宏而不是全局变量?
  • 这是一个品味问题。
  • @sepidehabadpour 大多数时候,您实际上应该不。 宏没有名称范围,没有类型安全等。一个好的经验法则是“不要使用如果也可以使用该语言的不同功能,则为宏。”
【解决方案2】:

您的问题为什么的明确答案是不可能的 - 没有理由使用像 #defines 这样的过时结构。主要原因是在过去这是定义常量的唯一方法(因为我们说的是constants而不是variables。所以主要原因是缺乏知识。

不要使用这样的结构 - 使用适当的 C++ 常量,例如

const double T12_re = 0.1;

【讨论】:

  • 其实 T12_re 等不是常量变量!会在main函数中修改!!
  • @sepidehabadpour 如果T12_re 是宏,则无法在运行时更改其值。
  • 如果你需要变量,那么#defines 是不行的——你不能在程序执行期间修改宏值。使用double T12_re = 0.1; 变量。
  • 你知道这不是我的程序。我正在研究开源软件 polsar pro 的代码,看看做了什么,并把它改成 matlab 中的代码
【解决方案3】:

预处理器指令不用于定义变量,#define 只是一种方便使用您将多次使用的代码或将来您可以修改而不更改放置代码的任何行的方法。 #define 只是将一个值替换为另一个值,例如:

#define PI 3.14159265
....
    float diameter = (circ / PI);

使用#define 和常量或变量最大的区别在于#define 的使用不会为这个值分配内存,编译时编译器只是将代码中的PI 替换为3.14159265。之所以使用这种方式,是因为在编译期间是不可更改的(与常量相同)并且不分配内存。

在编译过程中,C++编译器会生成一个替换掉定义的代码,所以上面的代码在编译过程中会是这样的:

float diameter = (circ / 3.14159265);

如果你想分配内存,只需使用常量:

const float PI = 3.14159265;

obs(#define 也用作宏)

【讨论】:

    【解决方案4】:

    我将尝试列举优点,其他答案已经涵盖了缺点。

    1. 这是创建常量的简洁方法

       #define PI 3.14
      

      PI 将被预处理器替换为每次遇到3.14,创建常量值的命名表示

    2. 另一种选择

       double const pi = 3.14; 
      

      可以像这样被黑客入侵

       const_cast<double>(pi) = 2.72; 
      

      这会导致未定义的行为。宏提供的文本替换不受const_cast

    3. 从 C++11 开始,您可以更好地将类型信息嵌入到文字中,从而减轻(一点)类型安全的考虑。请参阅here 更多信息,但对于一个简短的示例,请考虑例如,您始终可以声明一个具有安全类型的十秒倒计时常量

      #define CountDown 10s
      
    4. 最后但同样重要的是……现实是一片海滩(我希望这能通过审查)。在处理遗留代码时,您可能会遇到类似

      #define C1  112
      #define C2  113
      ....
      #define C332 443
      

      这就引出了一个问题:您在修改上述列表时选择一致性还是编程风格?当然,常数可能更多,而且分散在各处,当然总有选择的余地……

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-11-18
      • 2010-12-19
      • 1970-01-01
      • 2013-05-23
      • 2020-04-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多