【问题标题】:why does my gcc allow this empty function with pointer return type? [duplicate]为什么我的 gcc 允许这个具有指针返回类型的空函数? [复制]
【发布时间】:2020-09-26 00:15:45
【问题描述】:

以下函数在 Debian 上运行的 gcc 8.3 上成功编译并打印 hello 5

#include <stdio.h>

int* bar(int* x) {}

int main() {
  int x = 5;
  int* p = bar(&x);
  printf("hello %d\n", *p);
}

我对函数bar 感到困惑。它被声明为int*,但主体是空的,所以我实际上并没有告诉它返回任何东西。更令人担忧的是,为什么程序表现得好像我在 bar 的正文中说了 return x;?这种行为是在某处指定的还是只是一个意外?

【问题讨论】:

  • 使用函数的返回值定义为返回某些东西但实际上并没有这样做是未定义的行为。 (如果实践不佳,只需调用函数并忽略任何返回值都是有效的。)
  • 始终在启用额外详细警告的情况下构建(我推荐使用 GCC -Wall -Wextra -Wpedantic)并将所有警告视为错误。
  • 至于它返回你给它的原因,参数仍然保留在寄存器中。第一个参数的寄存器和最后一个参数的寄存器是一样的。
  • gcc 和-Wall 至少应该返回一个警告。

标签: c


【解决方案1】:

C 标准不要求使用非 void 返回类型声明的函数返回值。

标准规定,如果函数返回时没有返回值(因为执行流向其关闭}并且使用了函数的值,则未定义行为。但是,在某些情况下,函数在某些情况下返回值而不是其他情况下是有意义的。例如,您可以拥有一个根据命令参数设置或获取值的函数:

int AccessState(int Command, SomeStructure *S,...)
{
    switch (Command)
    {
        case 0: // Get the state.
            return S->Value;
        case 1: // Set the state from the optional int parameter following S.
             va_list ap;
             va_start(ap, S);
             S->Value = va_arg(S, int);
             va_end(ap);
             break;
    }
}

这样做是不寻常的(并且可能不是好的设计),因此编译器可能会对此发出警告。但是,为了符合 C 标准,C 实现不得拒绝非 void 函数,在该函数中控制可能到达关闭 }

【讨论】:

    【解决方案2】:

    该标准对返回语句有以下说法:

    ISO/IEC 9899:2018 §6.8.6.4 返回声明段落 2

    return 语句终止当前函数的执行并将控制权返回给它的调用者。一种 函数可以有任意数量的返回语句。

    这意味着编译器必须允许没有(或无法访问)返回语句的非 void 函数,以符合标准。 这会将返回值保留为未定义的行为。

    在这种情况下,用于第一个函数参数的寄存器也是用于返回值的寄存器。

    【讨论】:

      猜你喜欢
      • 2012-12-04
      • 2019-11-20
      • 2015-09-28
      • 1970-01-01
      • 2012-04-19
      • 2021-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多