#define和创建普通类型有什么区别?

时间:2013-11-14 17:13:41

标签: c++ c if-statement c-preprocessor

在C / C ++中,使用#define [和#ifndef #endif]创建值时有什么区别,当您可以使用intstd::string [C ++]呢?

#ifndef MYVAL
#define MYVAL(500)
#endif

//C++

cout << MYVAL << endl;

//C

printf(MYVAL);

//C++

int MYVAL = 500;
cout << MYVAL << endl;

//C
int MYVAL = 500;
printf(MYVAL);

6 个答案:

答案 0 :(得分:12)

你的假设是错误的。 #define不会创建“值”,它会在源代码中创建替换文本。它基本上与C或C ++无关。

答案 1 :(得分:6)

在我进入历史之前,这里是对两者之间差异的简要理解。

变量是变量。它们占用编译程序中的空间,除非用const标记它们(这是一个比宏更晚的开发),它们是可变的。

另一方面,宏是预处理。编译器永远不会看到宏。而是在编译之前处理宏。预编译器遍历代码,查找每个宏,并将其与宏文本逐字替换。这可能非常强大,有点用,而且相当危险(因为它修改代码并且在执行此操作时从不进行任何检查)。

此外,可以在命令行上设置宏。您可以在编译时根据需要定义任意数量的内容,如果您的代码检查该宏,则它的行为可能会有所不同。

宏在C ++之前很久就存在了。它们对很多东西很有用:

  • 您可以非常轻松地使用它们来表示常量表达式。它们可以节省空间,因为它们不需要任何变量(虽然常量表达式仍然需要在某处编译),并且它们存在于const说明符之前,因此它们是维护常量“变量”的简单方法“ - 预编译器会将所有MYVAR实例替换为500。
  • 你可以用它们做各种各样的功能。我实际上从来没有做过任何事情,因为这些好处似乎从未超过风险。未仔细构造的宏函数很容易破坏编译。但是我使用了一些预定义的宏函数。
  • #define宏仍然用于很多事情
    • 包含警卫(头文件通常在顶部定义了一个宏,并检查它是否已定义以确保它们不再添加它),
    • C中的TRUE和FAL,
    • 设置DEBUG模式,以便代码在调试和发布时的行为可以不同。举一个简单的例子,如果存在DEBUG宏,则断言是行为不同的函数。 (如果它不存在,则返回完全空的代码。)

在有限的情况下,你只是使用一个宏来表示一个常量表达式,你是对的 - 它们不再需要它们了。

答案 2 :(得分:5)

不同之处在于,使用宏(#),预处理器会对该符号进行搜索和替换。替换没有类型检查。

当你创建一个变量时,它会被输入,编译器会在你使用它的地方进行类型检查。

C / C ++编译器通常被认为是2遍编译器。第一遍是预处理器,它在宏上进行搜索和替换。第二遍是实际编译,其中创建了声明的变量。

宏通常用于创建更复杂的表达式,因此代码不必重复多次,因此语法更紧凑。它们很有用,但由于它们“盲目”搜索和替换性质而更加危险。此外,您无法使用调试器进入宏,因此可能难以进行故障排除。

此外,宏不遵守任何范围规则。 #define MYVAL(500)MYVAL替换为500,即使它出现在函数,全局范围,类声明等中,因此您必须更加小心。

答案 3 :(得分:2)

当你#define时,只要在你的代码中找到它就会被盲目替换:

#define the_answer 42
/// ...

int the_answer = /* oops! */

答案 4 :(得分:2)

您不应该使用#defines的重要原因很少。特别是对于你的问题,我会说,#define是纯文本替换,你不能限制宏的范围。即,您不能指定访问说明符或将其绑定到命名空间,因此一旦定义了宏,就可以在包含define的文件中的任何位置使用它们。

使用'const'变量,您可以将它们绑定在范围

这些可以提供帮助:http://www.parashift.com/c++-faq/const-vs-define.html

http://www.parashift.com/c++-faq/preprocessor-is-evil.html

答案 5 :(得分:1)

存在巨大差异:

a)#define MYVAL 500

这将创建一个宏。源代码中的每个出现都将由预处理器替换为其原始值。它完全忽略了范围,您无法更改其值

b)int MYVAL = 500;

这是遵守范围规则的常规变量,i。即当在函数内部声明时,它不能在它外面看到,它可以在另一个函数中被遮蔽等等......

另一方面,变量不能用于预处理器条件(#if#endif块)

最后一个例子:

#define MYVAL 500

int main() {
    int MYVAL = 10; // illegal, gets preprocessed as int 500 = 10;
}

与变量相同:

int MYVAL = 500

int main() {
    int MYVAL = 10; // legal, MYVAL now references local variable, ::MYVAL is the global variable
}