4

#define在 C/C++ 中,使用[and ] 创建值有什么区别#ifndef #endif,而您也可以轻松地使用 an intor std::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);
4

6 回答 6

12

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

于 2013-11-14T17:16:01.187 回答
6

在我进入历史之前,这里先简要了解两者之间的区别。

变量就是变量。它们在已编译的程序中占用空间,除非您使用const(这是比宏晚得多的开发)标记它们,否则它们是可变的。

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

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

宏早在 C++ 之前就存在了。它们对很多事情都很有用:

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

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

于 2013-11-14T17:28:39.377 回答
5

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

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

C/C++ 编译器通常被认为是 2-pass 编译器。第一遍是对宏进行搜索和替换的预处理器。第二遍是创建声明变量的实际编译。

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

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

于 2013-11-14T17:14:54.057 回答
2

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

#define the_answer 42
/// ...

int the_answer = /* oops! */
于 2013-11-14T17:18:26.843 回答
2

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

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

这些可能会有所帮助: http: //www.parashift.com/c++-faq/const-vs-define.html

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

于 2013-11-14T17:19:38.250 回答
1

这是个很大的差异:

一种)#define MYVAL 500

这将创建一个宏。它在源代码中的每一次出现都将被预处理器替换为其原始值。它完全忽略了范围,你不能改变它的价值

b)int MYVAL = 500;

这是一个遵守作用域规则的常规变量,即在函数内部声明时,它不能在函数外部看到,它可以在另一个函数中被隐藏,等等......

另一方面,变量不能用于预处理条件(#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
}
于 2013-11-14T17:17:39.803 回答