美文网首页
#if #ifdef #if defined 等几种常用的预处理

#if #ifdef #if defined 等几种常用的预处理

作者: 上午八点 | 来源:发表于2019-08-06 15:17 被阅读0次

    在写shader时经常会出现一些预编译指令比如 #if #ifdef #if defined 等,有的时候会感到困惑,所以决定仔细查一下具体的使用方法,并做一个简单的测试。

    #define

    #define 指令用于定义一个宏或者常量
    #define 有两种常用的格式:

    1. #define identifier token-string 定义一个宏,在预编译时会把所有identifier替换成token-string,可以用更容易理解的名称去代替一个常量,例如:#define PI 3.1415926
    2. #define identifier( argument0, ..., argumentN-1 ) token-string 定义一个类似函数一样的宏,例如:#define AREA(area, w, h) (area = w*h);
    // #define 的使用 //
    #define SOME_MACRO
    #define PI 3.141593
    

    定义宏时使用第一种方式,当没有指定 token-string 时,需要注意的两点是:

    1. 这个identifier依然是被定义了的,且可以使用#if defined 或 #ifdef 检测到的
    2. 所有identifier字符都会被移除,或者理解为所有identifier的地方都被替换成空字符串。

    详细信息可以参考 #define文档

    #if

    #if 是一个预处理指令,用来控制源文件中哪一部分会被编译。
    格式是: #if condition
    简单来说就是 #if 后面的条件语句(condition)如果执行结果不为0,则该#if语句块内的代码会被编译,否则就不会被编译。
    #elif 和 #else 可以类比为常规的用于判断条件的关键字 else if 和 else,区别是前面加了个#符号,用以表明该指令是在预处理阶段执行,而不是运行时执行。最后,在所有判断结束后需要用 #endif 来作为结尾,用于确定预处理语句的作用范围。

    // #if 的使用 //
    #define SOME_MACRO 0
    #if SOME_MACRO
        return float4(1,1,1,1);
    #else
        return float4(0,0,0,1);
    #endif
    

    以上代码结果返回黑色

    // #if 的使用 //
    #define SOME_MACRO
    #if SOME_MACRO
        return float4(1,1,1,1);
    #else
        return float4(0,0,0,1);
    #endif
    

    以上代码会报错: invalid or unsupported integer constant expression

    详细信息可以参考 #if文档

    #ifdef

    #ifdef 用于判断一个常量或者宏是否被定义
    格式是: #ifdef identifier
    identifier是一个宏或者常量,可以通过#define指令来定义,如果identifier被定义过,则#ifdef 语句块内的代码会被编译,否则不会被编译。
    #ifdef 只是判断一个常量或者宏是否被定义,不可以用于表达式判断,但是#if可以,例如:

    #define CONST_VALUE 3
    #if CONST_VALUE > 1
        return float4(1,1,1,1);
    #else 
        return float4(0,0,0,1);
    #endif
    
    #ifdef CONST_VALUE > 1      // 这样写会报错 //
    

    hlsl文档上的说法是#ifdef这种写法只是为了兼容以往版本,建议使用defined来判断,即使用 #if defined(MACRO) 这种形式,接下来就会说到。

    These directives are provided only for compatibility with previous versions of the language. The use of the defined operator with the #if directive is preferred.
    

    详细信息可以参考 #ifdef文档

    #if defined

    这是文档里更推荐的一种写法
    #if defined 和 #ifdef 都可以用来判断一个宏是否被定义,#if !defined 等同于 #ifndef。

    #define SOME_MACRO
    
    // #if defined 的使用 //
    #if defined(SOME_MACRO)
        // do something //
    #elif defined(OTHER_MACRO)
        // do something else //
    #endif
    
    // #ifdef 的使用 //
    #ifdef SOME_MACRO
        // do something //
    #endif
    
    #ifdef OTHER_MACRO
        // do something else //
    #endif
    

    总结

    1. 如果是根据一个宏是否被定义来决定一段代码要不要执行,建议使用 #if defined(MACRO) 方式
    2. 如果是根据一个表达式的值是否为0来决定一段代码要不要执行,建议使用 #if condition 方式
    3. #ifdef 用于判断宏或者常量是否被定义,不用于判断表达式,#if 可以用于判断表达式

    参考链接:

    https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-appendix-preprocessor

    https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-appendix-pre-define

    https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-appendix-pre-if

    https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-appendix-pre-ifdef

    https://stackoverflow.com/questions/3802988/difference-between-preprocessor-directives-if-and-ifdef

    测试工程地址:

    https://github.com/JasonTheCoderMichael/Preprocessor-Directives

    相关文章

      网友评论

          本文标题:#if #ifdef #if defined 等几种常用的预处理

          本文链接:https://www.haomeiwen.com/subject/zfxwdctx.html