C中的意外输出

时间:2014-08-30 04:27:51

标签: c recursion

以下是我的代码:

#include<stdio.h>

int i =5;

int main(i)
{
 if(i<10)
  printf(" %d\n",printf("%d",i+main(++i)));
 return 0;
}

输出

(同时在Ideone.com和Codeblocks中)

10 2

9 1

8 1

7 1

6 1

5 1

4 1

3 1

2 1

有人可以解释这个输出背后的原因吗?我期望91,81,....,51。此外,递归main()是否会导致意外输出?

PS:这是我在在线论坛中找到的一个程序。

3 个答案:

答案 0 :(得分:4)

首先,“implict int”规则在很久以前就被取缔了。 int main(i) { ...不是有效的函数声明。代码不能在兼容的C编译器中编译。

其次,表达式i+main(++i)没有足够的顺序。它会导致未定义的行为。如果没有在这些操作之间进行适当的排序,则读取变量i并在同一表达式中独立修改变量i是非法的。在这种情况下,语言没有定义行为。

实际上,我们不知道在i修改i+main(++i)的值之后或之后是否会读取++i中第一个i的值。语言不保证它。您的i等于1。对于i的值,不清楚i+main(++i)表达式的第一次评估是否等同于1+main(2)2+main(2)。这就是你的实验中发生的事情。您出于某种原因假设在i递增之前将读取第一个i。实际上,它以另一种方式起作用。

P.S。形式上,C语言(而不是C ++)似乎允许手动调用main。但是,您遇到的问题与main递归无关。

答案 1 :(得分:0)

拼图中有许多未定义的位,但printf是输出的关键。其他人详细说明了i+main(++i)表达式的非法性,所以让我们看看printf来分析输出:

printf(" %d\n",printf("%d",i+main(++i)));

有两个printf语句,其中必须首先评估printf("%d",i+main(++i))以便向另一个语句提供输出。所以选择未定义的值并将其插入%d。从现在开始,定义了行为。

man printf - 返回值:

Upon successful return, these functions return the number of characters printed

鉴于第一种情况printf("%d",i+main(++i))输出10,打印的两个字符的返回值为22的值传递给printf(" %d\n",..,第一次传递的输出为:

10 2

在第二次传递中选择未定义的行为,i+main(++i)的值为9printf("%d",i+main(++i))的回报现在是1,给出了第二行输出:

 9 1

依此类推......我无法解释未定义的10, 9, 8, ...,但其余的都是有道理的。

答案 2 :(得分:-1)

main的参数,即变量i,假设为int,它在本地接管全局i。作为main的参数,第一次调用它时它的值为#34;参数个数&#34; +1。所以,如果你运行你的程序没有参数,第一次调用main开始于1.尝试用一些参数运行你的程序,你会得到不同的结果。

对我来说

./a.out a b c
10 2
9 1
8 1 
7 1
6 1
5 1

了解评估顺序很棘手。考虑以下程序及其输出,可能会更清楚编译器正在做什么(或不做)。

#include<stdio.h>

int f(int x) {
  printf("f with x = %d\n", x);
  return x;  
}

int g(int x) {
  printf("g with x = %d\n", x);
  return x;  
}

int main()
{
  int i;

  i = 0;
  printf("%d\n", f(++i) + i + g(++i));

  i = 0;
  printf("%d\n", (f(++i) + i) + g(++i));

  i = 0;
  printf("%d\n", f(++i) + (i + g(++i)));
}

输出

f with x = 1
g with x = 2
4
f with x = 1
g with x = 2
4
f with x = 1
g with x = 2 
5