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

梦想的初衷 提交于 2019-12-23 12:14:03

问题


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?

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

回答1:


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.

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:

  • 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.
  • 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,
    • 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.)

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:


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.




回答3:


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.

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.




回答4:


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

#define the_answer 42
/// ...

int the_answer = /* oops! */



回答5:


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.

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

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

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




回答6:


There is a huge difference:

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;

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)

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
}


来源:https://stackoverflow.com/questions/19984032/what-is-the-difference-between-define-and-creating-a-normal-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!