#define 和创建普通类型有什么区别
What is the difference between #define and creating a normal type?
在 C/C++ 中,使用 #define
[和 #ifndef
#endif
] 创建值有什么区别,而您也可以使用 int
或 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);
你的假设是错误的。 #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
}
- 向量 <int> a {N, 0} 和 int arr a[N] = {0} 的时间复杂度有什么区别
- 在 .h 文件中的类中声明静态变量和在.cpp文件中声明"global"变量有什么区别
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 返回常量对象引用 (getter) 和仅返回字符串有什么区别?
- Qt:remove() 和 rmdir() 有什么区别
- 这 4 个 lambda 表达式之间有什么区别?
- 将向量作为类>(值)<向量启动和向量<类>[值]有什么区别
- typedef 枚举和枚举类有什么区别?
- &C::c 和 &(C::c) 有什么区别?
- ascii 和 unicode 在处理级别有什么区别吗?
- C 中的常量限定符和 C++ 中的常量限定符有什么区别?
- "ABC" 和 "ABC" ) 在C++中有什么区别?
- 空指针常量 (nullptr)、空指针值和空成员指针值之间有什么区别?
- 引用捕获和在 lambda 中通过引用发送参数有什么区别 (C++)
- 两种访问I2C总线的方法有什么区别?
- 两种模板示例有什么区别?
- 这两种C++语法之间有什么区别?
- lua 5.0.2 模块和 5.3.5 有什么区别?
- C++中"typedef"、"using"、"namespace"和"using namespace"有什么区别?
- std::enable_if 和 std::enable_if_t 有什么区别?