C++ 中 #define 指令的用途是什么?

发布于 2024-09-01 09:27:39 字数 37 浏览 4 评论 0原文

#define 指令的作用是什么?

What is the role of the #define directive?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

太阳哥哥 2024-09-08 09:27:39

#define 用于在 C 和 C++ 中创建宏。您可以在C 预处理器文档中阅读更多相关信息。简单的回答是它做了一些事情:

  1. 简单宏 - 基本上只是文本替换。编译时间常数就是一个很好的例子:

    <前><代码>#define SOME_CONSTANT 12

    只需将代码中出现的文本 SOME_CONSTANT 替换为 12 即可。此类宏通常用于提供代码块的条件编译。例如,项目中的每个源文件可能都包含一个标头,其中包含该项目的选项列表:

    <前><代码>#define OPTION_1
    #定义选项_2
    #undef OPTION_3

    然后项目中的代码块将用匹配的 #ifdef/#endif# 块包装,以在完成的项目中启用和禁用这些选项。使用 -D gcc 标志将提供类似的行为。然而,对于这种方法是否确实是为应用程序提供配置的好方法,存在着强烈的意见。

  2. 带参数的宏 - 允许您创建可以接受参数并操作它们的“类似函数”的宏。例如:

    #define SQUARE(x) ((x) * (x))
    

    将返回参数的平方作为其结果;小心潜在的操作顺序或副作用问题!下面的例子:

    int x = SQUARE(3); // 变为 int x = ((3) * (3));
    

    会工作得很好,但类似:

    int y = SQUARE(f()); // 变为 int y = ((f()) * (f()));
    

    将调用f()两次,甚至更糟:

    int z = SQUARE(x++); // 变为 int z = ((x++) * (x++));
    

    导致未定义的行为!

    使用某些工具,带有参数的宏也可以是可变参数,这可以派上用场。

正如下面的评论中提到的,过度使用宏或开发过于复杂或混乱的宏被许多人认为是不好的风格 - 一如既往,将代码的可读性、可维护性和可调试性置于“聪明”的技术技巧之上。

#define is used to create macros in C and in C++. You can read more about it in the C preprocessor documentation. The quick answer is that it does a few things:

  1. Simple Macros - basically just text replacement. Compile time constants are a good example:

    #define SOME_CONSTANT 12
    

    simply replaces the text SOME_CONSTANT with 12 wherever it appears in your code. This sort of macro is often used to provide conditional compilation of code blocks. For example, there might be a header included by each source file in a project with a list of options for the project:

    #define OPTION_1
    #define OPTION_2
    #undef  OPTION_3
    

    And then code blocks in the project would be wrapped with matching #ifdef/#endif# blocks to enable and disable those options in the finished project. Using the -D gcc flag would provide similar behaviour. There are strong opinions as to whether or not this method is really a good way to provide configuration for an application, however.

  2. Macros with arguments - allows you to make 'function-like' macros that can take arguments and manipulate them. For example:

    #define SQUARE(x)  ((x) * (x))
    

    would return the square of the argument as its result; be careful about potential order-of-operations or side-effect problems! The following example:

    int x = SQUARE(3);     // becomes int x = ((3) * (3));
    

    will works fine, but something like:

    int y = SQUARE(f());   // becomes int y = ((f()) * (f()));
    

    will call f() twice, or even worse:

    int z = SQUARE(x++);   // becomes int z = ((x++) * (x++));
    

    results in undefined behaviour!

    With some tools, macros with arguments can also be variadic, which can come in handy.

As mentioned below in the comments, overuse of macros, or the development of overly complicated or confusing macros is considered bad style by many - as always, put the readability, maintainability, and debuggability of your code above 'clever' technical tricks.

陈年往事 2024-09-08 09:27:39

#define(与其相反,#undef)可用于设置编译器指令,然后可以使用#ifndef 或#ifdef 对其进行测试。这允许在源文件中定义自定义行为。它通常用于针对不同环境进行编译或调试代码。

一个例子:

#define DEBUG



#ifdef DEBUG

//perform debug code

#endif

#define (and it's opposite, #undef) can be used to set compiler directives which can then be tested against using #ifndef or #ifdef. This allows for custom behaviors to be defined within the source file. It's used commonly to compile for different environments or debug code.

An example:

#define DEBUG



#ifdef DEBUG

//perform debug code

#endif
安稳善良 2024-09-08 09:27:39

#define 最常见的用途(far)是用于包含防护:

// header.hh
#ifndef HEADER_HH_
#define HEADER_HH_

namespace pony {
// ...
}

#endif

#define 的另一个常见用途是创建配置文件,通常是 config.h 文件,我们在其中根据各种状态和条件#define 宏。然后,在我们的代码中,我们使用 #ifdef#elif Defined() 等测试这些宏,以支持不同情况下的不同编译。这并不像 include-guard 习惯用法那么可靠,在这里您需要小心,因为如果分支错误,那么您可能会得到非常模糊的编译器错误,或更糟糕的运行时行为。

一般来说,除了包含保护之外,您还需要仔细考虑(最好是两次)问题,并看看是否可以使用编译器而不是预处理器来解决它。编译器只是比预处理器更聪明。不仅如此,编译器不可能混淆预处理器,而预处理器肯定会混淆和误导编译器。

The most common use (by far) of #define is for include guards:

// header.hh
#ifndef HEADER_HH_
#define HEADER_HH_

namespace pony {
// ...
}

#endif

Another common use of #define is in creating a configuration file, commonly a config.h file, where we #define macros based on various states and conditions. Then, in our code we test these macros with #ifdef, #elif defined() etc. to support different compiles for different situations. This is not as solid as the include-guard idiom and you need to be careful here because if the branching is wrong then you can get very obscure compiler errors, or worse, runtime behavior.

In general, other than for include guards you need to think through (twice, preferably) about the problem, and see if you can use the compiler rather than the preprocessor to solve it. The compiler is just smarter than the preprocessor. Not only that, but the compiler can't possibly confuse the preprocessor, whereas the preprocessor most definitely can confuse and mislead the compiler.

各自安好 2024-09-08 09:27:39

#define 指令有两个常见用途。

第一个是控制编译器的行为方式。为此,我们还需要#undef、#ifdef 和#ifndef。 (还有#endif...)

你可以用这种方式制作“编译器逻辑”。一个常见的用途是激活或不激活代码的调试部分,如下所示:

#ifdef DEBUG

//debug code here

#endif

例如,您可以通过编写 #define DEBUG 来编译调试代码。

这种逻辑东西的另一个用途是避免双重包含。 ..

例如,文件 A,#includes 文件 B 和 C。但是文件 B 还包含 C。这可能会导致编译错误,因为“C”存在两次。

解决方案是这样写:

#ifndef C_FILE_INCLUDED
#define C_FILE_INCLUDED

//the contents of header "c" go here.

#endif

#define 的另一个用途是 make 宏。

最简单的由简单的替换组成,例如:

#define PI 3.14159265

float perimeter(float radius) {
    return radius*2*PI;
}

#define SHOW_ERROR_MESSAGE printf("An serious error happened");

if ( 1 != 1 ) { SHOW_ERROR_MESSAGE }

然后您还可以制作接受参数的宏,printf 本身通常是一个宏,在头文件中使用 #define 创建。

但不应该这样做,原因有二:
首先,速度操作系统宏与使用内联相同,其次,我们有 C++ 模板,它允许对变量类型的函数进行更多控制。因此,使用带有参数的宏的唯一原因是制作奇怪的结构,这在以后将很难理解,就像元编程的东西一样......

The #define directive has two common uses.

The first one, is control how the compiler will act. To do this, we also need #undef, #ifdef and #ifndef. (and #endif too...)

You can make "compiler logic" this way. A common use is to activate or not a debug portion of the code, like that:

#ifdef DEBUG

//debug code here

#endif

And you would be able to for example compile the debug code, by writing a #define DEBUG

Another use of this logic stuff, is to avoid double includes...

Example, file A, #includes file B and C. But file B also includes C. This likely will result in a compilation error, because "C" exists twice.

The solution is write:

#ifndef C_FILE_INCLUDED
#define C_FILE_INCLUDED

//the contents of header "c" go here.

#endif

The other use of #define, is make macros.

The most simple ones, consist of simple substitutions, like:

#define PI 3.14159265

float perimeter(float radius) {
    return radius*2*PI;
}

or

#define SHOW_ERROR_MESSAGE printf("An serious error happened");

if ( 1 != 1 ) { SHOW_ERROR_MESSAGE }

Then you can also make macros that accept arguments, printf itself usually is a macro, created with a #define in a header file.

But this should not be done, for two reaons:
first, the speed os macros, is the same of using inline, and second, we have c++ templates, that allow more control over functions with variable type. So, the only reason to use macros with arguments, is make strange constructs, that will be hard to understand later, like metaprogrammed stuff...

幼儿园老大 2024-09-08 09:27:39

在 C++ 中,#define 具有非常狭窄的专门角色:

  • 标头防护,在其他答案
  • 与标准库交互中描述。例如,在包含 windows.h 之前 #defining WINDOWS_LEAN_AND_MEAN 会关闭某些经常出现问题的宏,例如 MAX。
  • 涉及字符串化(即打印调试消息的宏)或标记粘贴的高级宏。

您应该避免将#define 用于以下目的。原因有很多;请参阅此常见问题解答条目

  • 编译时常量。使用 const 代替。
  • 简单的宏函数。请改用内联函数和模板。

In C++, #define has very narrow, specialized roles:

  • Header guards, described in other answers
  • Interacting with the standard libraries. For instance, #defining WINDOWS_LEAN_AND_MEAN before including windows.h turns off certain often-problematic macros like MAX.
  • Advanced macros involving stringization (ie, macros that print debugging messages) or token-pasting.

You should avoid using #define for the following purposes. The reasons are many; see for instace this FAQ entry.

  • Compile-time constants. Use const instead.
  • Simple macro functions. Use inline functions and templates instead.
嘦怹 2024-09-08 09:27:39

CC++#define允许您创建预处理器宏。

在正常的 CC++ 构建过程中,首先发生的事情是预处理器运行,预处理器在源文件中查找预处理器指令,例如 #define< /strong> 或 #include,然后用它们执行简单的操作。

对于#define指令,预处理器会进行简单的基于文本的替换。

例如,如果您有代码,

#define PI 3.14159f

float circum = diameter*PI;

预处理器会将其转换为:

float circum = diameter* 3.14159;

只需将 PI 实例替换为相应的文本即可。这只是 #define 语句的最简单形式,有关更高级的用途,请查看此 文章 来自 MSDN

in C or C++ #define allows you to create preprocessor Macros.

In the normal C or C++ build process the first thing that happens is that the PreProcessor runs, the preprocessor looks though the source files for preprocessor directives like #define or #include and then performs simple operations with them.

in the case of a #define directive the preprocessor does simple text based substitution.

For example if you had the code

#define PI 3.14159f

float circum = diameter*PI;

the preprocessor would turn it into:

float circum = diameter* 3.14159;

by simply replacing the instances of PI with the corresponding text. This is only the simplest form of a #define statement for more advanced uses check out this article from MSDN

苦笑流年记忆 2024-09-08 09:27:39

inCorrectUseOfHashDefine()

{

#define 的作用是让那些继承你的代码的人感到困惑,因为他们突然出现这样的语句:

foreverandever

因为:

#define foreverandever for(;;)

}

请优先选择常量而不是 #define。

它还用于设置编译器指令......

inCorrectUseOfHashDefine()

{

The role of #define is to baffle people who inherit your code with out of the blue statements like:

foreverandever

because of:

#define foreverandever for(;;)

}

Please favour constants over #define.

It also for setting compiler directives...

落日海湾 2024-09-08 09:27:39

关于 #define 的大多数事情已经被告知,但尚不清楚 C++ 对于它们的大多数用途有更好的替代品:

  1. #define 定义数值常量可以很容易地用 const“变量”替换,而作为 #define,它不会编译后的可执行文件中并不真正存在。 AFAIK 它可以用于几乎所有可以使用 #define 数值常量的情况,包括数组边界。对我而言,主要优点是此类常量的类型清晰,因此无需“只是为了确定”而在宏中添加强制转换,并且具有作用域,因此它们可以保留在名称空间/类/函数中,而不会污染所有应用。

 

const int max_array_size=50;
int an_array[max_array_size];
  1. #define创建宏:宏通常可以用模板代替;例如,可怕的 MAX 宏

 

#define MAX(a,b)    ((a)<(b)?(b):(a))

,它有几个缺点(例如重复的参数求值,不可避免的内联扩展),可以用 max 函数代替,

template<typename T> T & max(T & a, T & b)
{
    return a<b?b:a;
}

它可以是类型安全的(在这个版本中,两个参数被强制为相同类型),可以内联扩展以及不(这是编译器的决定),仅对参数求值一次(在调用时),并确定作用域。可以在此处找到更详细的说明。

尽管如此,宏仍然必须用于包含保护,以创建某种奇怪的语言扩展,这些扩展可以扩展到更多代码行,具有不平衡的括号等。

Most things about #defines have been already told, but it's not clear that C++ has better replacements for most of their uses:

  1. #define to define numerical constants can be easily replaced by a const "variable", that, as a #define, doesn't really exist in the compiled executable. AFAIK it can be used in almost all the situations where you could use a #defined numerical constant, including array bounds. The main advantage for me is that such constants are clearly typed, so there's no need to add casts in the macros "just to be sure", and are scoped, so they can be kept in namespaces/classes/functions, without polluting all the application.

 

const int max_array_size=50;
int an_array[max_array_size];
  1. #define to create macros: macros can often be replaced by templates; for example, the dreaded MAX macro

 

#define MAX(a,b)    ((a)<(b)?(b):(a))

, which has several downsides (e.g. repeated arguments evaluation, inevitable inline expansion), can be replaced by the max function

template<typename T> T & max(T & a, T & b)
{
    return a<b?b:a;
}

which can be type-safe (in this version the two arguments are forced to be of the same type), can be expanded inline as well as not (it's compiler decision), evaluates the arguments just once (when it's called), and is scoped. A more detailed explanation can be found here.

Still, macros must still be used for include guards, to create some kind of strange language extensions that expand to more line of code, that have unbalanced parenthesis, etc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文