为什么这个代码的三个数字是“-666 3289 1617”并且能够打印最后一行?

Why the three numbers for this code is "-666 3289 1617" and able to print the last line?

#include <stdio.h>
#include <inttypes.h>
#include <stdlib.h>
static int64_t arr[] = { 20047, 75106, 19594, 88069, 22445, 82238 };
const static int N = sizeof(arr)/sizeof(*arr);

static void fail(){
        puts("Nope!");
        exit(EXIT_FAILURE);
     }

    static void func_one(int64_t r, int64_t i, int64_t g){
        if ( r - g / 7 + 3 * i / 11 )
              fail();
    }
static void func_two(int z, int64_t b){
        int o = b;
        for(; z<N; ++z) {
           if ((z % 2) == 0)
              continue;
           o += arr[z];
        }
        if (o != 188394)
           fail();
    }
static void func_three(int d, int64_t e){
        if (d<N) {
          if (d % 2)
            func_three(++d, e);
          else func_three(d + 1, e * arr[d]);
      } else if (e != 190100988)
         fail();
    }

int main(){
    int64_t p, q, v;
    printf("Please enter the right three numbers: ");
    fflush(stdout);
    if (scanf("%" SCNd64 " %" SCNd64 " %" SCNd64,&p,&q,&v) != 3)
    fail();
    arr[0] = p;
    arr[5] = q;
    arr[4] = v;
    func_two(0, 21930);
    func_three(1, 6);
    func_one(p, q, v);
    puts("Exactly! Good job.");
    }

我传递了三个输入值:“-666 3289 1617”。这些输入对代码做了什么并且能够打印最后一行“Exactly!干得好。”?有什么办法可以找到其他输入值吗?这里到底发生了什么。

如果函数的测试未通过,func… 函数中的每一个都会调用 fail,并且 fail 例程以“不!”终止程序。信息。因此,目标是获得“完全正确!做得好。”消息需要通过测试。

该程序尝试从输入中读取三个数字,分别称为 pqv。应该注意的是,如果存在各种错误,例如算术溢出或由于 scanf 未接收到合适的输入而使用未初始化的变量,则程序的行为未由 C 标准定义,所以程序可能会打印出“Exactly!做得好。”在这种情况下。但是,此答案的其余部分将在分析程序时排除未定义的行为。

读取数字pqv后,程序将它们放在arr中的特定位置,留下arrp、75106、19594、88069、vq.

然后程序调用func_two(0, 21930)func_two 使用第一个参数 0 作为循环计数器,并使用第二个参数 21930 开始累加和。在循环中,它对循环计数器的偶数值 z 不执行任何操作。对于 z 的奇数值,它会将 arr[z] 添加到总和中。因此,对于 21930,它将 arr[1]arr[3]arr[5] 相加,形成总和 21930 + 75106 + 88069 + q。要通过,这个总和必须等于 188394。所以我们有 21930 + 75106 + 88069 + q = 188394,其解决方案是 q = 3289.

然后程序调用func_three(1, 6)func_three 也使用它的第一个参数作为循环计数器,d,并通过递归的方式使用 e 作为累加积,e。当 d 为奇数时,func_three 仅使用递增的 d 调用自身,而 e 没有变化。当 d 是偶数时,func_three 以递增的 de 乘以 arr[d].

调用自身

由于d从1开始,第一次偶数是2的时候。因此,func_threee开始设置为6,然后乘以arr[2] 然后 arr[4],产生 6 • 19594 • v。然后递归结束,因为 d 到达数组大小的末尾 N,并且函数应用其测试:此乘积必须等于 190100988。所以我们有 6 • 19594 • v = 190100988,其解为v = 1617.

然后函数调用func_one(p, q, v),我们现在知道一定是func_one(p, 3289, 1617)。它调用这些参数 rig 并计算 r - g / 7 + 3 * i / 11,它必须为零才能通过测试。代入我们得到 p - 1617 / 7 + 3 * 3289 / 11,它减少到 p - 231 + 897 并进一步减少到 p + 666。显然,要使其为零,p 必须为 −666。

因此,产生输出“Exactly!做得好。”没有未定义的行为是 -666 3289 1617 或等价物,例如带有前导零的相同数字。