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

What is the difference between #define and creating a normal type?

本文关键字:什么 区别 类型 创建 #define      更新时间:2023-10-16

在 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);

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

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

变量

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

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

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

宏早在C++年之前就已经存在了。 它们在很多方面都很有用:

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

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

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

当您创建变量时,它是类型化的,编译器将在您使用它的位置进行类型检查。

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

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

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

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

#define the_answer 42
/// ...
int the_answer = /* oops! */

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

使用"const"变量,您可以将它们绑定到作用域中

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

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

有一个巨大的区别:

a) #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
}