C+中的#define指令的目的是什么+;? 代码< >代码>指令> < p> 定义> 用于在C和C++中创建宏。你可以在网站上阅读更多关于它的信息。快速的答案是它可以做一些事情:

C+中的#define指令的目的是什么+;? 代码< >代码>指令> < p> 定义> 用于在C和C++中创建宏。你可以在网站上阅读更多关于它的信息。快速的答案是它可以做一些事情:,c++,c-preprocessor,C++,C Preprocessor,简单的宏-基本上只是文本替换。编译时常量就是一个很好的例子: #define SOME_CONSTANT 12 只要将出现在代码中的文本SOME_CONSTANT替换为12。这类宏通常用于提供代码块的条件编译。例如,项目中的每个源文件可能包含一个标题,其中包含项目的选项列表: #define OPTION_1 #define OPTION_2 #undef OPTION_3 然后,项目中的代码块将使用匹配的#ifdef/#endif块进行包装,以在完成的项目中启用和禁用这些选项。使用-Dg

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

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

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

  • 带参数的宏-允许您制作“类似函数”的宏,这些宏可以接受参数并对其进行操作。例如:

    #define SQUARE(x)  ((x) * (x))
    
    将返回参数的平方作为其结果;注意潜在的操作顺序或副作用问题!下面是一个例子:

    int x = SQUARE(3);     // becomes int x = ((3) * (3));
    
    威尔工作正常,但有点像:

    int y = SQUARE(f());   // becomes int y = ((f()) * (f()));
    
    将调用
    f()
    两次,甚至更糟:

    int z = SQUARE(x++);   // becomes int z = ((x++) * (x++));
    
    导致未定义的行为

    使用某些工具,还可以使用带有参数的宏,这很方便

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

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

    例如:

    #define DEBUG
    
    
    
    #ifdef DEBUG
    
    //perform debug code
    
    #endif
    
    < C或C++ > <强>定义> <强>允许您创建预处理器宏。

    在正常的C或C++构建过程中,首先发生的是预处理器运行,预处理器看起来是预处理器指令的源文件,比如“强> >定义< <强> >或<强>包含< /强>,然后执行简单操作。< /P> 对于#define指令,预处理器执行简单的基于文本的替换

    例如,如果你有代码

    #define PI 3.14159f
    
    float circum = diameter*PI;
    
    预处理器会将其转换为:

    float circum = diameter* 3.14159;
    
    通过简单地用相应的文本替换PI的实例。这只是#define语句的最简单形式,用于更高级的用途请从MSDN中查看此语句

    {

    #define的作用是让继承您代码的人措手不及,比如:

    foreverandever
    
    因为:

    #define foreverandever for(;;)
    
    }

    请支持常数而不是定义

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

    define指令有两种常见用途

    第一个是控制编译器将如何操作。要做到这一点,我们还需要#undef、#ifdef和#ifndef。(和#endif too…)

    您可以用这种方式创建“编译器逻辑”。常见的用法是激活或不激活代码的调试部分,如下所示:

    #ifdef DEBUG
    
    //debug code here
    
    #endif
    
    例如,您可以通过编写#define debug来编译调试代码

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

    例如,文件A#包括文件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;
    }
    

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

    但这不应该这样做,因为有两个原因: 首先,速度OS宏与内联相同,第二,我们有C++模板,允许对变量类型的函数进行更多的控制。因此,使用带有参数的宏的唯一原因是生成奇怪的构造,这以后很难理解,比如元编程的东西…

    到目前为止,
    \define
    最常用的用法是用于包含保护:

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

    一般来说,除了include-guard,您需要仔细考虑(最好两次)这个问题,看看是否可以使用编译器而不是预处理器来解决它。编译器比预处理器更聪明。不仅如此,编译器也不可能混淆预处理器,而预处理器最能迷惑和误导编译器。

    < P>大多数关于“X”定义的事情已经被告知,但不清楚C++对它们的大多数使用有更好的替代:

  • #define-to-define数值常量可以很容易地被const“variable”替换,而const“variable”作为#define,实际上并不存在于编译后的可执行文件中。AFAIK它可以用于几乎所有可以使用#定义的数值常量的情况,包括数组边界。对我来说,主要的优点是这些常量类型清晰,
    // header.hh
    #ifndef HEADER_HH_
    #define HEADER_HH_
    
    namespace pony {
    // ...
    }
    
    #endif
    
    const int max_array_size=50;
    int an_array[max_array_size];
    
    #define MAX(a,b)    ((a)<(b)?(b):(a))
    
    template<typename T> T & max(T & a, T & b)
    {
        return a<b?b:a;
    }