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

c 语言里面 #if 不可以这样用吗?

  •  
  •   amiwrong123 · 2022-10-22 15:34:32 +08:00 · 1919 次点击
    这是一个创建于 767 天前的主题,其中的信息可能已经有所发展或是发生改变。
    typedef enum {
        log_level_error = 0,
        log_level_warning = 1,
        log_level_info = 2,
        log_level_dbg = 3,
        log_level_all = 4,
    } my_log_level;
    
    #define SMALL 1
    #define LARGE 4
    
    static const int current_log_level = log_level_info;
    
    int main()
    {
    #if (current_log_level > SMALL)
        int b;
    #endif
    
    #if (current_log_level > log_level_error)
        int b;
    #endif
        b = 2;
    
        return 0;
    }
    

    可能我这个问题有点蠢,但为啥我上面的程序会编译报错呢,两种形式都没有把int b;给编译到,对于#if的用法有点不太明白了。

    13 条回复    2022-10-22 22:10:17 +08:00
    westoy
        1
    westoy  
       2022-10-22 15:36:18 +08:00
    这不是运行时的 if , 这是宏里的 if 啊, 编译前会替换掉的, 拿来处理变量当然会有问题了
    overloadtanxxx2
        2
    overloadtanxxx2  
       2022-10-22 15:37:02 +08:00
    #if 是预编译
    预编译 比 编译早呀。
    赋值是编译期间的操作。预编译的时候还没赋值
    overloadtanxxx2
        3
    overloadtanxxx2  
       2022-10-22 15:38:16 +08:00
    你试试 改成 > -1 ,看看 int b 能不能编译到。估计就能编译到了
    amiwrong123
        4
    amiwrong123  
    OP
       2022-10-22 15:41:13 +08:00
    @westoy #1
    @overloadtanxxx2 #3
    谢谢,我大概理解了,所以我这个程序正确的写法应该是把:
    static const int current_log_level = log_level_info;
    替换成
    #define current_log_level 2

    最好也把 枚举定义也替换成宏:
    typedef enum {
    log_level_error = 0,
    log_level_warning = 1,
    log_level_info = 2,
    log_level_dbg = 3,
    log_level_all = 4,
    } my_log_level;
    替换为
    #define log_level_error 0
    #define log_level_warning 1
    #define log_level_info 2
    #define log_level_dbg 3
    #define log_level_all 4

    应该是这样做吧
    overloadtanxxx2
        5
    overloadtanxxx2  
       2022-10-22 15:49:27 +08:00
    @amiwrong123 感觉没什么毛病。肯定可以达到 定义不同等级打印不同等级日志的效果
    overloadtanxxx2
        6
    overloadtanxxx2  
       2022-10-22 16:00:17 +08:00   ❤️ 1
    程序符号表有一个变量 current_log_level 。在程序跑之前。根据不同编译器,值不一样。一般是 0 。预编译运行时,这个值不符合条件
    amiwrong123
        7
    amiwrong123  
    OP
       2022-10-22 16:02:28 +08:00
    @overloadtanxxx2 #6
    ok ,理解你的意思,总之,在#if 里面,不可以依赖这种全局变量的值,就算能依靠也是不可靠的
    ligiggy
        8
    ligiggy  
       2022-10-22 16:19:15 +08:00
    推荐看一本书,《程序员的自我修养—链接、装载与库》。
    jimmy980352
        9
    jimmy980352  
       2022-10-22 16:30:34 +08:00
    可能编译器认为会出现变量 b 不被定义的情况,试试#if....#elif...#else...#endif 的每个区间都定义 b
    amiwrong123
        10
    amiwrong123  
    OP
       2022-10-22 16:35:23 +08:00
    @jimmy980352 #9
    嗯,你意思我理解了。留出一个#else...来保证编译到 int b;

    不过我的目的是:用 打印日志等级 来控制一些打印。

    正常来说,我那个程序会写成:
    #if (current_log_level > log_level_error)
    printf("error log\n");
    #endif

    但是我又发现这么写 好像不能起到控制编译的作用,实际效果是:我那么写 是永远不会被编译到。
    iamzuoxinyu
        11
    iamzuoxinyu  
       2022-10-22 16:52:31 +08:00
    @amiwrong123 为什么不干脆
    #if LOG_WARN
    // print sth
    #endif

    #if LOG_ERROR
    // print err
    #endif

    这样,编译时直接 gcc -DLOG_WARN -DLOG_ERROR 想怎么指定怎么指定……
    iamzuoxinyu
        12
    iamzuoxinyu  
       2022-10-22 16:54:09 +08:00
    #ifdef 更好。
    lance6716
        13
    lance6716  
       2022-10-22 22:10:17 +08:00 via Android
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1819 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 16:32 · PVG 00:32 · LAX 08:32 · JFK 11:32
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.