【问题标题】:What is this C idiom (if (1))?这个 C 习语是什么(如果(1))?
【发布时间】:2017-08-21 05:19:11
【问题描述】:

我注意到 openssl 源代码中有一个奇怪的习语,here 并在下面重复:

if ((in == NULL) && (passwds == NULL)) {
        if (1) {                                    (* <---- HERE *)
#ifndef OPENSSL_NO_UI
            /* build a null-terminated list */
            static char *passwds_static[2] = { NULL, NULL };

            passwds = passwds_static;
            if (in == NULL)
                if (EVP_read_pw_string
                    (passwd_malloc, passwd_malloc_size, "Password: ",
                     !(passed_salt || in_noverify)) != 0)
                    goto end;
            passwds[0] = passwd_malloc;
        } else {
#endif
            BIO_printf(bio_err, "password required\n");
            goto end;
        }
}

看来这段代码相当于:

if ((in == NULL) && (passwds == NULL)) {
#ifndef OPENSSL_NO_UI
        /* build a null-terminated list */
        static char *passwds_static[2] = { NULL, NULL };

        passwds = passwds_static;
        if (in == NULL)
            if (EVP_read_pw_string
                (passwd_malloc, passwd_malloc_size, "Password: ",
                 !(passed_salt || in_noverify)) != 0)
                goto end;
        passwds[0] = passwd_malloc;
#else
        BIO_printf(bio_err, "password required\n");
        goto end;
#endif
}

我排除了一些解释:

  • 可能是为passwds_static 引入块作用域,但封闭的if 将起到类似的作用
  • 它可能是一个结构,通过几次有意义的转换变得毫无意义,但那个结构就在那里since the introduction of OPENSSL_NO_UI

我在这里遗漏了什么吗?这个if (1)有什么好处?这在其他代码库中使用吗?

谢谢!

【问题讨论】:

  • 在我看来,它的唯一目的是为了避免和#else子句出于任何原因
  • @CristiFati - 不。这与#if 1 无关,因为该构造根本没有出现在问题中。关于if(1)
  • 确实,这与#if 0#if 1if (0) 无关。
  • 唯一明显的区别是单独使用预处理器不会产生关于不可访问代码的警告。但我非常怀疑这就是意图。

标签: c openssl idioms conditional-compilation


【解决方案1】:

看了其他类似的地方,I found an explanation

if (1) { /* This is a trick we use to avoid bit rot.
          * at least the "else" part will always be
          * compiled.
          */
#ifdef AF_INET6
    family = AF_INET6;
} else {
#endif
    BIOerr(BIO_F_ACPT_STATE, BIO_R_UNAVAILABLE_IP_FAMILY);
    goto exit_loop;
}

在大多数情况下(我猜包括他们的 CI),OPENSSL_NO_UI 没有定义,因此两个 分支都被编译。如果其中一个分支的 API 使用了变化,编译器会发现它,并且可以修复它,而无需测试所有编译时开关。

【讨论】:

    【解决方案2】:

    它显然用于删除不应执行的代码,类似于使用#ifdef 编译器开关。大多数情况下,像这样的奇怪事情比其他任何事情都表明版本控制不佳。

    请注意,这不是推荐的做法 - 不应存在在任何情况下都不会执行的源代码。使用版本控制是更好的做法,或者如果这不可能使用编译器开关,或者如果这不可能,则“注释掉”代码。

    【讨论】:

      【解决方案3】:

      声明:

      if(1) {
      

      总是有一个匹配的左大括号作为右大括号。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-01
        • 1970-01-01
        • 2012-01-05
        • 2011-11-13
        • 1970-01-01
        相关资源
        最近更新 更多