2006年9月28日星期四

一段有意思的C代码

糊里糊涂的写了一个有点意思的代码:

#include<stdio.h>
int main() {
    char name[10]; //复制错了代码,应该是这样的;不好意思。
    printf("Please tell me what's your name: ");
    scanf("%s", name);
    printf("Hello, %s!\n", name);
}


用Dev-C++编译后,执行时发现,当你在Please tell me what's youe name: 后面输入28个英文字符后,回车,打印出问候语,并再次出现Please tell me what's youe name: 提示行!再次输入28个字符,则再次出现。如此往复!

我想请教一下,这个死循环怎么产生的?不知道其他编译器编译出来会不会这样。

另外,输入的字符数小于28个的时候,一切正常,大于28个的时候,运行报错,但是依然可以显示正确的结果。

最关键的问题是Why 28?

寻求答案中...

updated:

写blog时贴错了代码,已经修正了。

又做了更多的数组越界实验,发现在name[NUM]中,NUM在9-16时,都会出现上面描述的情况,即输入28字符出现死循环;NUM>16,则运行正常;NUM<=8,则输入12个字符可出现死循环。这样是不是略为容易解释了呢。

2 条评论:

  1. 奇怪,每执行一句,栈都向下生长,而 scanf 应该是向上的,所以会把栈破坏掉一部分。想想入栈时返回值、返回地址、参数的顺序是什么呢,有可能是编译器为函数执行预先分配栈空间,把返回值,返回地址和参数放在栈空间末尾(低端),因此 scanf 可以正常返回,继续执行下一句。下一句 printf 与 scanf 这一句的栈格式相同,因此 name 没有被破坏。然后 main 返回地址坏掉了.. 不知道怎么解释了,为什么坏掉了还会跳转到 main。
    cygwin 不会这样,也许 dev-c++ 的 gcc 版本有些低?什么版本的?

    回复删除
  2. Dev-C++的版本号是4.9.9.2,gcc版本是3.4.2的。

    C:\Dev-Cpp\bin>gcc -v
    Reading specs from ../lib/gcc/mingw32/3.4.2/specs
    Configured with: ../gcc/configure --with-gcc --with-gnu-ld --with-gnu-as --host=
    mingw32 --target=mingw32 --prefix=/mingw --enable-threads --disable-nls --enable
    -languages=c,c++,f77,ada,objc,java --disable-win32-registry --disable-shared --e
    nable-sjlj-exceptions --enable-libgcj --disable-java-awt --without-x --enable-ja
    va-gc=boehm --disable-libgcj-debug --enable-interpreter --enable-hash-synchroniz
    ation --enable-libstdcxx-debug
    Thread model: win32
    gcc version 3.4.2 (mingw-special)

    回复删除