【问题标题】:In C language, what's the purpose of statement that is after return?在C语言中,return之后的语句的目的是什么?
【发布时间】:2021-11-14 00:07:35
【问题描述】:

最近看了一个公共C库的代码,发现函数定义如下:

void* block_alloc(void** block, size_t* len, size_t type_size)
{
    return malloc(type_size);

    (void)block;
    (void)len;
}

不知道return后是否会到达statements。如果不是,这两条将某些数据转换为 void 的语句的目的是什么?

【问题讨论】:

  • 大概是为了使编译器未使用的 var 警告静音?不,在方法/函数中的 return 语句之后不能到达任何语句。
  • 我认为这是block_alloc 具有此特定签名的要求,但它实际上并不需要blocklen,因此(void)block(void)len 抑制任何“未使用的变量" 警告。
  • 将这些强制转换放在函数末尾是非常愚蠢的,因为现在您可能会收到关于无法访问代码的不同警告。演员表应该放在函数的开头。

标签: c type-conversion


【解决方案1】:

正如 Basil 所指出的,(void) 语句可能旨在消除有关未使用参数的编译器警告。但是 - 您可以将 (void) 语句移到 return 之前,以减少它们的混淆,并具有相同的效果。

事实上,还有另一种方法可以达到相同的效果,而无需使用任何额外的语句。今天已经有许多编译器支持它,尽管在 C2X 之前它还没有正式出现在 C 标准中:

void* block_alloc(void**, size_t*, size_t type_size)
{
    return malloc(type_size);
}

如果您不命名参数,典型的编译器不会期望您使用它们。

【讨论】:

  • 在 C 中,省略参数名称似乎是非标准的(显然直到 C23):godbolt.org/z/9Ybf8s619
  • @mediocrevegetable1:感谢您指出这一点,我想我现在已经太习惯 C++了。
【解决方案2】:

首先,出现在块中return 之后的这些语句将永远不会被执行。

通过阅读一些 C 标准来检查,例如 n1570

其次,在某些编译器上(可能GCC 10 调用为gcc -Wall -Wextra),无用的语句可能会避免一些警告。

在我看来,在返回之前对这些语句进行编码不会改变优化编译器发出的机器代码(使用gcc -Wall -Wextra -O2 -fverbose-asm -S 来检查和发出汇编代码)并使 C 源代码更易于理解。

GCC 提供了一个名为 the variable __attribute__ 的扩展名 unused

也许在您的软件中,您的block_alloc 被分配给一些重要的函数指针(请求其签名)

【讨论】:

  • 我上面评论的稍长版本。
  • 但是我添加了指向有趣信息的超链接。
【解决方案3】:

它用于使警告静音。一些编程标准要求函数体中使用的所有参数,没有它,它们的静态分析器将无法传递代码。

在某些情况下,在返回后添加,防止生成代码:

int foo(volatile unsigned x)
{
    (void)x;
    return 0;
}

int foo1(volatile unsigned x)
{
    return 0;
    (void)x;
}
foo:
        mov     DWORD PTR [rsp-4], edi
        mov     eax, DWORD PTR [rsp-4]
        xor     eax, eax
        ret
foo1:
        mov     DWORD PTR [rsp-4], edi
        xor     eax, eax
        ret

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-22
    • 2013-08-17
    • 1970-01-01
    • 1970-01-01
    • 2022-11-17
    • 1970-01-01
    • 1970-01-01
    • 2018-10-24
    相关资源
    最近更新 更多