为什么输出正确并带有注释返回

问题描述

最近我一直在使用 Codility 进行锻炼,并且成功完成了 Passing Cars 练习。

#include <stdio.h>

int PassingCars(int someArray[],int N)
{
        if(N == 1)
        return 0;

        int counter = 0,result = 0;
        for(int i = 0; i < N; i++)
        {
                if(someArray[i] == 0)
                        ++counter;

                if(someArray[i] == 1)
                {
                        result += counter;
                        if(result > 1e9)
                                return -1;
                }
        }

        //return result;
}

int main()
{
        int arrOne[] = {0,1,1};

        printf("%d\n",PassingCars(arrOne,sizeof(arrOne)/sizeof(arrOne[0])));

        return 0;
}

即使结果的返回被注释,输出也是正确的。怎么样?

解决方法

您的 CPU 不关心缺少“返回”

要执行 C 程序,其 source code 必须由 compiler 编译/翻译为 machine code

机器代码只是一堆instruction that the CPU can execute一个接一个, 导致 registers 的值或内存位置发生变化。 当这些执行的一部分应该将值移交给另一部分时, 随后执行,它必须通过寄存器传递这些值。 但是当“返回值寄存器”没有设置时,我可能会包含一些先前指令结果的随机值。您的 CPU 不关心两个代码段之间缺少的切换,因为它只关心一条一条的执行指令,而不知道这些指令的更大逻辑是什么。

在您的情况下,这种寄存器中的旧值恰好与结果应该在 PassingCars 中设置/返回的值相同。可能是因为您有计算输入数组长度的代码,并且在执行过程中经常使用该值,这实际上是要返回的函数的正确结果。

要检查这一点,您可以将源代码编译为汇编代码并对其进行逆向工程:

$ gcc -S ./main.c
$ cat ./main.s
        .file   "main.c"
        .text
        .globl  PassingCars
        .type   PassingCars,@function
PassingCars:
.LFB0:
        .cfi_startproc
        endbr64
.
.
.

但这相当耗时。

使用编译器警告避免丢失返回值

为避免将来出现此类问题,您可以使用编译器警告,例如 -Wall

gcc -Wall ./main.c
./main.c: In function ‘PassingCars’:
./main.c:23:1: warning: control reaches end of non-void function [-Wreturn-type]
   23 | }
      | ^

这是有关 gcc warning options 的文档的链接。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...