【问题标题】:Missings in a definition of function which returns value - what type of error?返回值的函数定义中缺少什么类型的错误?
【发布时间】:2019-08-06 12:28:51
【问题描述】:

假设我有以下函数定义:

int foo () {
    int x;
    x = x + 2;
}

如你所见,这个函数被声明为返回一个int 值,但是没有return 语句,它也没有获取任何参数。

给定上面定义的这个函数,它构成什么类型​​的错误 - 语法?语义?运行 ?没有任何错误类型?

【问题讨论】:

标签: c compilation


【解决方案1】:

这不被认为是错误的语法。按照'c'标准是可以的。因此它可以编译,但结果将是不可预测的。

正如 cmets 中提到的,这只是糟糕的编程。现代编译器可以检测程序中的此类常见问题。因此,使用gcc -Wall,您可以获得以下关于缺少返回语句(控制到达...)和未初始化变量的诊断信息。

%> gcc a.c -Wall
 a.c: In function 'foo':
 a.c:1:1: warning: control reaches end of non-void function [-Wreturn-type]
  int foo () { int x; x=x+2;}
  ^~~
 a.c:1:22: warning: 'x' is used uninitialized in this function [-Wuninitialized]
  int foo () { int x; x=x+2;}
                      ~^~~~
 a.c:1:18: note: 'x' was declared here
  int foo () { int x; x=x+2;}

【讨论】:

    【解决方案2】:

    两者都没有。如果调用者使用返回值,则它是有效的 C 但未定义的行为。 C 标准 6.9.1/12(语义)说:

    如果到达终止函数的},并且函数调用的值被 调用者,行为未定义。

    【讨论】:

    • 行为未定义。仅当使用返回值时。
    • 但是,您是否会说,这种未定义行为的原因将在语义分析期间发现?
    • @galik 没有。两者都不是。只要不存在的返回值被忽略,具有类似功能的程序就是正确的程序。
    • @AnttiHaapala:具有类似函数且忽略返回值(并且根据 C 标准没有其他缺陷)的程序将被符合标准的 C接受实施,但这并不能使它正确。要正确,程序必须符合其规范。也就是说,它必须正确执行它所要求的任何任务并满足任何其他要求(例如时间和空间的限制,可能对可验证性的限制等等)。
    • @AnttiHaapala:是的,标准确实定义了它,并且定义不限于满足 C 标准的语法和约束,而是“在所有其他方面都是正确的”。以免您认为那些“所有其他方面”仅限于标准的内容,它继续说“对正确的数据进行操作”,这显然超出了程序本身的源代码,两者在语法和语义上。因此,“正确的程序”必须在所有其他方面真正正确,包括对其规范的期望。
    【解决方案3】:

    当程序的含义与预期不符时,就是语义错误。

    首先,让我们更正函数,使其初始化x

    int foo(void)
    {
        int x = 0;
        x = x + 2;
    }
    

    其次,让我们假设函数的返回值在某处被使用。然后 C 6.9.1 12 告诉我们:

    除非另有说明,否则如果到达终止函数的},并且调用者使用了函数调用的值,则行为未定义。

    如果我们进一步假设作者不打算编写具有未定义行为的程序并且没有其他东西(例如编译器实现)定义行为,那么程序foo的含义不是作者想要的——他们打算让它以某种定义的行为执行,但它没有,因此出现了错误。这是程序源代码含义的错误,是语义错误。

    【讨论】:

    • 但是假设没有提供有关程序或其意图的其他信息 - 它是否一定是在语义分析期间应该发现的错误?
    • @galik:什么是“语义分析”?编译器可能会也可能不会诊断问题。
    • @ Eric Postpischil 我的意思是理论上。假设我们只知道上面定义函数的方式是假的。一定是语义错误吗?
    • @galik:我不知道“上面定义函数的方式是假的”是什么意思。陈述是真的还是假的。定义事物的方式不分真假。如果函数没有按照预期执行,则为错误。有正式的数学/逻辑系统来验证程序是否符合规范,并且在这样的系统中,该功能可能会被证明不符合其规范。
    • @galik:某些编译器会在编译该函数时发出警告,具体取决于设置。仅从函数的源代码来看,编译器无法确定存在错误,因为允许在不返回值的情况下离开函数。如果使用和函数定义对编译器都是可见的,则编译器可以在使用函数时检测到错误。当前版本的 Clang 和 GCC 似乎没有这样做。鉴于此,可以通过良好的测试发现错误。如果不是,则程序部署时可能存在错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-12
    • 2020-04-04
    相关资源
    最近更新 更多