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

时间:2021-10-18 16:35:48

In C/C++, what is the difference between using #define [and #ifndef #endif] to create values, when you can easily do it with an int or std::string [C++] too?

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

6 个解决方案

#1


6  

Before I jump into history, here's a brief understanding of the difference between the two.

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

Variables are, well, variables. They take up space in the compiled program, and unless you mark them with const (which is a much later development than macros), they're mutable.

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

Macros, on the other hand, are preprocessed. The compiler never sees the macro. Instead, the macros are handled before compiling. The precompiler goes through the code, finds every macro, and replaces it verbatim with the macro text. This can be very powerful, somewhat useful, and fairly dangerous (since it's modifying code and never does any checking when doing so).

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

Also, macros can be set on the command line. You can define as many things as you want when you are compiling, and if your code checks for that macro, it can behave differently.

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

Macros existed long before C++. They have been useful for many things:

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

  • You can use them very easily to represent constant expressions. They can save space, because they don't require any variables (though the constant expression still needs to be compiled in somewhere), and they existed before the const specifier, so they were an easy way to maintain constant "variables" - the precompiler would replace all instances of MYVAR with 500.
  • 您可以非常轻松地使用它们来表示常量表达式。它们可以节省空间,因为它们不需要任何变量(虽然常量表达式仍然需要在某处编译),并且它们存在于const说明符之前,因此它们是维护常量“变量”的简单方法 - 预编译器用500替换MYVAR的所有实例。

  • You can do all sorts of functions with them. I actually never made any myself, because the benefits never seemed to outweigh the risks. Macro functions that aren't carefully constructed can easily break your compile. But I have used some predefined macro functions.
  • 你可以用它们做各种各样的功能。我实际上从来没有做过任何事情,因为好处似乎从未超过风险。未仔细构造的宏函数很容易破坏编译。但我使用了一些预定义的宏函数。

  • #define macros are still used for many things
    • include guards (header files usually have a macro defined at the top, and check if it's defined to make sure they don't add it again),
    • 包含警卫(头文件通常在顶部定义一个宏,并检查它是否已定义以确保它们不再添加它),

    • TRUE and FALSE in C,
    • C中为TRUE,FALSE,

    • setting DEBUG mode so that code can behave differently for debugging and release. As one simple example, assertions are functions that behave differently if the DEBUG macro is present. (If it's not present, it returns completely empty code.)
    • 设置DEBUG模式,以便代码在调试和发布时的行为可以不同。举一个简单的例子,如果存在DEBUG宏,则断言是表现不同的函数。 (如果它不存在,则返回完全空代码。)

  • #define宏仍然用于许多事情,包括警卫(头文件通常在顶部定义了一个宏,并检查它是否被定义以确保它们不再添加它),在C中为TRUE和FALSE,设置DEBUG模式如此该代码在调试和发布方面的行为可能不同。举一个简单的例子,如果存在DEBUG宏,则断言是表现不同的函数。 (如果它不存在,则返回完全空代码。)

In the limited case where you're simply using a macro to represent a constant expression, you're right - they're no longer needed for that.

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

#2


12  

Your assumptions are wrong. #define doesn't create "values", it creates replacement text in your source code. It has basically nothing to do with C or C++ at all.

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

#3


5  

The difference is that with the macros (#) the preprocessor does a search and replace on that symbol. There is no type checking on the replace.

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

When you create a variable, it is typed and the compiler will do type checking where you use it.

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

C/C++ compilers are often thought of as 2-pass compilers. The first pass is the preprocessor which does search and replace on macros. The second pass is the actual compilation where the declared variables are created.

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

Macros are often used to create more complex expressions so the code doesn't have to be repeated more than once and so the syntax is more compact. They are useful, but also more dangerous due to their 'blind' search and replace nature. In addition, you can't step into a macro with a debugger so they can be harder to troubleshoot.

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

Also, macros do not obey any scoping rules. #define MYVAL(500) will replace MYVAL with 500 even if it occurs in functions, global scope, class declarations, etc. so you have to be more careful in that way.

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

#4


2  

When you #define something, it will be blindly replaced whenever it's found in your code:

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

#define the_answer 42
/// ...

int the_answer = /* oops! */

#5


2  

There are few important reasons why you shouldn't use #defines. For your questions in particular I would say, #define are plain text replacements and you can't limit the scope of the macro. i.e, you can't specify an access specifier or bind it to a namespace, so once you define the macros you can use them anywhere in the files where the define is included.

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

With 'const' variables you can have them bound in a scope

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

These could help : http://www.parashift.com/c++-faq/const-vs-define.html

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

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

#6


1  

There is a huge difference:

这是个很大的差异:

a) #define MYVAL 500

a)#define MYVAL 500

This will create a macro. Each of its occurences in the source code will be replaced by its raw value by the preprocessor. It completely ignores the scope and you cannot change its value

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

b) int MYVAL = 500;

b)int MYVAL = 500;

This is a regular variable that obeys scope rules, i. e. when declared inside a function, it cannot be seen outside it, it can be shadowed within another function, etc...

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

On the other hand, variables cannot be used in preprocesor conditions (#if, #endif blocks)

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

One last example:

最后一个例子:

#define MYVAL 500

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

Same with variable:

与变量相同:

int MYVAL = 500

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

#1


6  

Before I jump into history, here's a brief understanding of the difference between the two.

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

Variables are, well, variables. They take up space in the compiled program, and unless you mark them with const (which is a much later development than macros), they're mutable.

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

Macros, on the other hand, are preprocessed. The compiler never sees the macro. Instead, the macros are handled before compiling. The precompiler goes through the code, finds every macro, and replaces it verbatim with the macro text. This can be very powerful, somewhat useful, and fairly dangerous (since it's modifying code and never does any checking when doing so).

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

Also, macros can be set on the command line. You can define as many things as you want when you are compiling, and if your code checks for that macro, it can behave differently.

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

Macros existed long before C++. They have been useful for many things:

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

  • You can use them very easily to represent constant expressions. They can save space, because they don't require any variables (though the constant expression still needs to be compiled in somewhere), and they existed before the const specifier, so they were an easy way to maintain constant "variables" - the precompiler would replace all instances of MYVAR with 500.
  • 您可以非常轻松地使用它们来表示常量表达式。它们可以节省空间,因为它们不需要任何变量(虽然常量表达式仍然需要在某处编译),并且它们存在于const说明符之前,因此它们是维护常量“变量”的简单方法 - 预编译器用500替换MYVAR的所有实例。

  • You can do all sorts of functions with them. I actually never made any myself, because the benefits never seemed to outweigh the risks. Macro functions that aren't carefully constructed can easily break your compile. But I have used some predefined macro functions.
  • 你可以用它们做各种各样的功能。我实际上从来没有做过任何事情,因为好处似乎从未超过风险。未仔细构造的宏函数很容易破坏编译。但我使用了一些预定义的宏函数。

  • #define macros are still used for many things
    • include guards (header files usually have a macro defined at the top, and check if it's defined to make sure they don't add it again),
    • 包含警卫(头文件通常在顶部定义一个宏,并检查它是否已定义以确保它们不再添加它),

    • TRUE and FALSE in C,
    • C中为TRUE,FALSE,

    • setting DEBUG mode so that code can behave differently for debugging and release. As one simple example, assertions are functions that behave differently if the DEBUG macro is present. (If it's not present, it returns completely empty code.)
    • 设置DEBUG模式,以便代码在调试和发布时的行为可以不同。举一个简单的例子,如果存在DEBUG宏,则断言是表现不同的函数。 (如果它不存在,则返回完全空代码。)

  • #define宏仍然用于许多事情,包括警卫(头文件通常在顶部定义了一个宏,并检查它是否被定义以确保它们不再添加它),在C中为TRUE和FALSE,设置DEBUG模式如此该代码在调试和发布方面的行为可能不同。举一个简单的例子,如果存在DEBUG宏,则断言是表现不同的函数。 (如果它不存在,则返回完全空代码。)

In the limited case where you're simply using a macro to represent a constant expression, you're right - they're no longer needed for that.

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

#2


12  

Your assumptions are wrong. #define doesn't create "values", it creates replacement text in your source code. It has basically nothing to do with C or C++ at all.

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

#3


5  

The difference is that with the macros (#) the preprocessor does a search and replace on that symbol. There is no type checking on the replace.

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

When you create a variable, it is typed and the compiler will do type checking where you use it.

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

C/C++ compilers are often thought of as 2-pass compilers. The first pass is the preprocessor which does search and replace on macros. The second pass is the actual compilation where the declared variables are created.

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

Macros are often used to create more complex expressions so the code doesn't have to be repeated more than once and so the syntax is more compact. They are useful, but also more dangerous due to their 'blind' search and replace nature. In addition, you can't step into a macro with a debugger so they can be harder to troubleshoot.

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

Also, macros do not obey any scoping rules. #define MYVAL(500) will replace MYVAL with 500 even if it occurs in functions, global scope, class declarations, etc. so you have to be more careful in that way.

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

#4


2  

When you #define something, it will be blindly replaced whenever it's found in your code:

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

#define the_answer 42
/// ...

int the_answer = /* oops! */

#5


2  

There are few important reasons why you shouldn't use #defines. For your questions in particular I would say, #define are plain text replacements and you can't limit the scope of the macro. i.e, you can't specify an access specifier or bind it to a namespace, so once you define the macros you can use them anywhere in the files where the define is included.

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

With 'const' variables you can have them bound in a scope

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

These could help : http://www.parashift.com/c++-faq/const-vs-define.html

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

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

#6


1  

There is a huge difference:

这是个很大的差异:

a) #define MYVAL 500

a)#define MYVAL 500

This will create a macro. Each of its occurences in the source code will be replaced by its raw value by the preprocessor. It completely ignores the scope and you cannot change its value

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

b) int MYVAL = 500;

b)int MYVAL = 500;

This is a regular variable that obeys scope rules, i. e. when declared inside a function, it cannot be seen outside it, it can be shadowed within another function, etc...

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

On the other hand, variables cannot be used in preprocesor conditions (#if, #endif blocks)

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

One last example:

最后一个例子:

#define MYVAL 500

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

Same with variable:

与变量相同:

int MYVAL = 500

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