【问题标题】:Why would someone use #define to define constants?为什么有人会使用#define 来定义常量?
【发布时间】:2011-09-10 13:37:29
【问题描述】:

这是一个简单的问题,但为什么有人会使用#define 来定义常量?

有什么区别

#define sum 1const int sum = 1;

【问题讨论】:

  • 我真的很想说,“因为他们是 n00bs”...+1 好问题
  • 是的,这个应该会带来一些有趣的答案
  • @user 非常简单,如果您使用 C++ 编程——只需遵循 Scott Meyer 的建议 Item#1 'Prefer const and inline to #define'。使用 '#define' 作为 const 不起作用的最后手段。例如,标题包含保护等。
  • 这里有一个技巧可以降低得到许多不同答案的风险:不要在标题中提出问题而在正文中提出不同的问题。它们相似,但有不同的回答方式。
  • @Nemo 当然,否则他怎么能真正快速地获得一些代表点? :P

标签: c++ constants c-preprocessor


【解决方案1】:

来自 Introduction to programming with C++ 由 Daniel Liang 写的:

当您使用#define 指令定义常量时,该常量为 未存储在内存中。常量将替换为值 编译器。当您使用 const 关键字声明常量时, 常量和变量一样存储在内存中。

如果常量需要在多个程序中使用,请使用#define头文件中定义,以便包含在其他程序中。如果常量只在一个程序中使用,使用const 声明效率更高。

【讨论】:

    【解决方案2】:

    简单来说

    #define sum 1  /*is pre processed*/
    

    这意味着,在预处理阶段完成后,sum 不存在。

    const int sum = 1; /*is compiled/linked*/
    

    这意味着sum 一直存在,直到可执行文件从您的程序中生成。

    【讨论】:

    • 不回答 OP 的问题,即为什么使用一个而不是另一个。 (不想苛刻,但它真的没有回答,对不起。)-1
    • @Mehrdad,说明为什么使用#define 会写得太多。这就是为什么我简单地说#define 是经过预处理的。 :)
    【解决方案3】:

    没有人不应该!
    实际上,出于多种原因,人们应该更喜欢 const int sum = 1; 而不是 #define sum 1

    基于范围的机制:

    #defines 不尊重作用域,因此无法创建类作用域命名空间。而 const 变量可以在类中作用域。


    在编译错误期间避免奇怪的神奇数字:

    如果您使用的是#define,它们会在预编译时被预处理器替换因此,如果您在编译期间收到错误,那将会令人困惑,因为错误消息不会引用宏名称而是值,它会出现一个突然的值,人们会浪费大量时间在代码中跟踪它。


    易于调试:

    同样出于#2 中提到的相同原因,调试#define 并不会提供任何帮助。


    因此,避免上述情况const将是一个更好的选择。

    【讨论】:

    • @Martinho,如果任何答案以 SO 中的 # 开头,那么它会以 大粗体 显示所有内容。
    • +1 是有道理的,尽管我猜这是好事还是坏事还有待商榷。
    • @Mehrdad, #define X 可以使用#undef X 虚拟地确定范围
    • @iammilind:不是真的。如果它是之前定义的,它会丢失之前的值——它像推送/弹出堆栈。
    • 大声笑,“为什么有人会使用 #define ?” “出于多种原因:1)它很烂 2)它很烂 3)它很烂”
    【解决方案4】:

    对于您刚刚给出的示例,我通常会使用 const。当然,#define 可以用于其他地方的条件编译:

    #if SOME_DEFINE == 1
        // Conditional code
    #endif
    

    这是你不能用 const 做的事情。如果您不需要从预处理器访问该值,我会说使用 const 除非有某种原因无法做到这一点。 C++ FAQ lite 中有一些关于这方面的内容,他们正确地指出,仅仅因为预处理器是“邪恶的”,并不意味着你永远不需要它。

    【讨论】:

    • 我不会说常量不能用于条件编译。您可以专门为常量创建一个模板。以here 为例。
    • 是的,但我不能使用它来有条件地 #include 取决于平台或类似的东西。所以我想说它不能用于某些类型的条件编译。 ;)
    • 我会使用构建系统来做出这样的选择,而不是defines。
    • 我没有就如何进行条件编译提出任何建议,我只是指出你可以用#defines 做的一件可能的事情,而这不是(很容易)用 const 完成的。
    【解决方案5】:

    #define 有许多不同的应用程序,但您的问题似乎是关于一个特定的应用程序:定义命名常量。

    在 C++ 中,很少有理由使用#define 来定义命名常量。

    #define 通常在 C 代码中广泛使用,因为 C 语言在定义常量方面与 C++ 有很大不同。简而言之,const int 对象在 C 中不是常量,这意味着在 C 中定义真正常量的主要方法是使用 #define。 (另外,对于int 常量,可以使用枚举)。

    【讨论】:

    • @AndreyT 伙计,我在这里很害怕:| ,这个真实答案的规则是什么,得分的原因是什么?
    • @user788552 更多点的答案并不意味着它总是正确的
    • static const int 和 enum {...} 是 C++ 中的实常数常量
    • @CygnusX1:在 C++ 中,const int 前面不需要static。在 C++ 中,const 对象默认具有内部链接。
    • @BlueRaja - Danny Pflughoeft:嗯,只是因为语言是这样定义的。在 C 语言中,您不能将 const int 对象用作 case 标签、位域大小、非 VLA 数组的数组大小,特别是因为 const int 对象在 C 中不是常量。C 中的术语“常量”指的是文字常量(如25)和枚举成员,但不是const 对象。
    【解决方案6】:

    始终尝试使用“const int”,而不是#define。

    仅当您的预处理器代码可能被其他工具读取时才使用#define,并且它更容易与预处理器一起使用,而不是解析语言。

    这也是定义稍后由#if/#else/#endif 检查的唯一方法

    【讨论】:

      【解决方案7】:

      #define 是使包含保护之类的东西起作用所必需的,因为 C++ 没有 真正的 模块导入系统。

      #define 导致文字文本替换。预处理器了解如何标记源代码,但不知道它的实际含义。当您编写#define sum 1 时,预处理器会检查您的代码并查找标记sum 的每个实例,并将其替换为标记1

      这有很多限制:#define sq(x) x * x 如果你像sq(3+3) 那样使用它,它将无法正常工作;并且将#define 用于常量不以任何方式尊重范围,也不会将任何类型的类型与常量相关联。但是,可以使用#define(尤其是与其他一些特殊的东西,如### 预处理器运算符结合使用)来做一些原本不可能的魔法(除非手动执行预处理器所做的事情)。

      【讨论】:

      • 我想说第一句话是一个答案,其余的只是 OP 可能已经知道的事情。
      • 我认为应该在 C++ 中使用 #pragma once 而不是包含保护。
      • #pragma once 是特定于编译器的。该标准没有定义 pragma 的含义。
      • 但它得到了广泛的支持,通常不需要为此目的使用#define。
      • 同意,但大多数(所有?)编译器都支持它。
      【解决方案8】:

      const int 只是一个不能改变的 int。 #define 是 C 预处理器的指令,它不仅仅用于定义常量。

      更多详情请看这里:http://en.wikipedia.org/wiki/C_preprocessor

      【讨论】:

      • 不回答 OP 的问题,即为什么使用一个而不是另一个。 (不想苛刻,但它真的没有回答,对不起。)-1
      【解决方案9】:

      第一个是预处理器指令,在编译器编译你的代码之前,它会通过并将 sum 替换为 1。第二个在内存中声明一个变量来保存该数量。我确信可以争论哪个是最好的,但是“const int”在 C++ 中可能更常见(当涉及到数字常量时)。

      http://www.geekpedia.com/KB114_What-is-the-difference-between-sharpdefine-and-const.html

      【讨论】:

      • const int 没有在内存中声明变量;链接的文章不正确。
      • @Don: 你不能const int sum = 1; const int* sum_ptr = ∑吗?
      • 不回答 OP 的问题,即为什么使用一个而不是另一个。 (不想苛刻,但它真的没有回答,对不起。)-1
      • “在内存中声明一个变量”可能不够精确,无法准确地描述为真或假,真的。
      • @Martinho Fernandes:C++ 标准 7.1.5.1.3:“指向 cv 限定类型的指针或引用不需要实际指向或引用 cv 限定对象,但它被视为确实如此。”抛弃 const-ness 并分配给这样的指针或引用具有未定义的行为。
      猜你喜欢
      • 1970-01-01
      • 2017-08-03
      • 1970-01-01
      • 2017-12-23
      • 1970-01-01
      • 2013-09-27
      • 1970-01-01
      • 1970-01-01
      • 2011-08-25
      相关资源
      最近更新 更多