V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
liuidetmks
V2EX  ›  程序员

请教一个 C 宏的写法

  •  
  •   liuidetmks · 2022-02-18 09:19:39 +08:00 · 2200 次点击
    这是一个创建于 1000 天前的主题,其中的信息可能已经有所发展或是发生改变。
    #if defined(DEBUG)
    #define TODO(MSG)
    #else
    /// 抛出 MSG 编译错误
    #define TODO(MSG) #error MSG  // 这样不行. #好像不能在后面
    #end
    
    

    在 DEBUG 模式, 忽略 TODO(MSG)
    Rlease 模式, 抛出编译错误 类似于 #error MSG

    不知道有没有类似于 defined()预处理方法直接抛出错误

    if(xxx){
    /// 主流程
    }else{
    TODO('其他特殊情况,需要处理')
    }
    
    

    这样在 release 编译时候,抛出错误 "其他特殊情况,需要处理"

    第 1 条附言  ·  2022-02-18 11:12:31 +08:00
    感谢大家的回复,
    目前,有两种做法,一种直接抛出一个语法错误 define TODO(a) TODO##a
    第二是 _Static_assert 抛出英文错误(中文会展示\uxxxx ) 唯一的困扰是,其他人看到这个错误会莫名其妙

    这个问题太 tricky
    或者说有更好的解决方法吗.
    一个业务 分支太且深,一次只能专注于一个链路。想减轻下大脑负担, 有什么好的实践吗?
    15 条回复    2022-02-18 10:56:31 +08:00
    philon
        1
    philon  
       2022-02-18 09:31:54 +08:00
    宏定义里`#`会用于字符串转换和拼接,不能用宏来定义新的宏

    另外我不太理解你的需求,难道想把预处理和运行时的逻辑混在一起?怕是不现实
    zhyl
        2
    zhyl  
       2022-02-18 09:40:04 +08:00
    xyz1001
        3
    xyz1001  
       2022-02-18 09:46:41 +08:00   ❤️ 1
    C++11 的话可以这么写:

    ```
    #if defined(DEBUG)
    #define TODO(MSG)
    #else
    /// 抛出 MSG 编译错误
    #define TODO(MSG) static_assert(false) // 这样不行. #好像不能在后面
    #endif

    int main() {
    TODO("test");
    return 0;
    }
    ```

    C 的话不是很熟悉有没有对应的写法
    nicebird
        4
    nicebird  
       2022-02-18 09:46:53 +08:00
    不知道咋写,如果 c++直接 static_assert(false, msg)
    yolee599
        5
    yolee599  
       2022-02-18 09:52:36 +08:00
    1. “#” 用于连接两个字符串,不能这样用
    2. 宏是编译预处理,不是运行时,所以不可能在运行的时候执行 #error “some msg”
    liuidetmks
        6
    liuidetmks  
    OP
       2022-02-18 09:56:39 +08:00
    @zhyl 我先想的是这样,单这样只能笼统的报出一个语法错误,不能提示后面的消息. 看来也只能这样了

    @philon 需求就是,开发过程中,有很多流程,有时候只能专注于某一个流程,其他的流程只能打上 TODO 标签,
    在 debug 的时候可以正常调试,但是 release 时候会提示哪些分支没完成。
    takitooru
        7
    takitooru  
       2022-02-18 10:03:27 +08:00
    #ifdef DEBUG
    #define TODO(MSG)
    #else
    #error Invalid TODO_
    #endif
    ysc3839
        8
    ysc3839  
       2022-02-18 10:03:48 +08:00 via Android
    zhyl
        9
    zhyl  
       2022-02-18 10:05:53 +08:00   ❤️ 1
    或者用这种方式:
    ```
    #define DO_PRAGMA_(x) _Pragma(#x)
    #define DO_PRAGMA(x) DO_PRAGMA_(x)
    #define TODO(msg) DO_PRAGMA(GCC error msg)

    int main() {
    TODO("compile error");
    TODO("编译错误");
    return 0;
    }
    ```

    已知的问题:clang 下 msg 如果是中文不会显示错误内容
    Kasumi20
        10
    Kasumi20  
       2022-02-18 10:19:22 +08:00
    除非可以转义#号,不然只能一行变三行:
    #ifndef NDEBUG
    #error "TODO MSG"
    #endif
    lonewolfakela
        11
    lonewolfakela  
       2022-02-18 10:43:14 +08:00   ❤️ 1
    @xyz1001 C 语言( c11 )的话,应该可以
    #if defined(DEBUG)
    #define TODO(MSG)
    #else
    /// 抛出 MSG 编译错误
    #define TODO(MSG) _Static_assert(false, MSG)
    #endif
    lesismal
        12
    lesismal  
       2022-02-18 10:45:21 +08:00
    #if defined(DEBUG)
    #define TODO(MSG)
    #else
    #define TODO error // 没必要还非得是宏函数吧
    #end
    liuidetmks
        13
    liuidetmks  
    OP
       2022-02-18 10:47:31 +08:00
    @lonewolfakela 这个我试了,只能英文 .. 中文是 \uxxxx, 不过目的也达到了,到错误处看代码就行了,只是别人编译的话看到错误可能莫名其妙 感谢回复
    exiledkingcc
        14
    exiledkingcc  
       2022-02-18 10:48:49 +08:00
    最简单的方案就是上面提到的 _Static_assert
    jackmod
        15
    jackmod  
       2022-02-18 10:56:31 +08:00
    不求严谨的话直接写一个超长的字符串也行
    展开之后就是按变量名对待的,其结果就是未定义变量
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1315 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 17:52 · PVG 01:52 · LAX 09:52 · JFK 12:52
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.