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

Joe*_*Joe 4 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);
Run Code Online (Sandbox Code Playgroud)
//C++

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

//C
int MYVAL = 500;
printf(MYVAL);
Run Code Online (Sandbox Code Playgroud)

Ker*_* SB 12

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


Sco*_*ica 6

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

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

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

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

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

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

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

  • 应该教会学习C或C++的人,预处理是与后续语义操作分开的阶段,而不是"编译器永远不会看到宏".预处理是语言翻译的一部分(例如,根据C 2011 5.1.1.2),它可以集成到编译器中(如GCC所做的那样).这可以产生诸如智能错误消息(用其他信息编织预处理效果)或由于源代码中比较早阶段预处理错误更早的后期语义违规而无法编译的程序(例如` #error`). (2认同)

edt*_*guy 5

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

创建变量时,会对其进行类型化,编译器会在您使用它的位置进行类型检查.

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

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

此外,宏不遵守任何范围规则. #define MYVAL(500)将取代MYVAL500即便如此,你必须以这种方式更加小心出现它的功能,全球范围内,类声明等.