2015-06-21 76 views
-3

我最近在这里回答了一个问题,其中问题是输入几个代码句并打印出来。我的代码是这样的:为什么即使在我没有分配内存时也能工作?

#include<stdio.h> 

int main() { 
    clrscr(); 
    int line, i; 

    char (*string)[100]; 
    printf("How many line?\n"); 
    scanf("%d",&line); 
    getchar(); 

    for(i=0;i<line;i++) { 
     gets(string[i]); 
    } 

    printf("You entered:\n"); 
    for(i=0;i<line;i++) { 
     puts(string[i]); 
    } 

    return 0; 
} 

正如你看到的,我还没有分配的任何内存到各个串即s[0]s[1],......但令人惊讶的我的编译器没有给我任何的警告或它的错误,它完美的作品。

所以我发布了这个代码,坦白地说它有很多downvotes(我知道我配得上它)。你能解释为什么这个代码可以工作,而不是给出分割错误吗?

我的输出如下所示:

Output

+1

这只是未定义的行为。段错误或崩溃是没有必要的。并且不要使用'gets'。你知道为什么。另外,如果您使用'clrscr()',请包含'conio.h' –

+6

C和C++都删除'gets'。我强烈建议不要使用它。你可能想知道'string'是一个指向100个字符数组的指针,而不是100个char *数组。 – chris

+6

纯粹的运气不好,它没有崩溃。请参阅[为什么'gets()'太危险了](http://stackoverflow.com/questions/1694036/why-is-the-gets-function-dangerous-why-should-it-not-be-used )。 –

回答

3
char (*string)[100]; 

OK,string表示指针100 char,但它未初始化。因此,它代表一个任意的地址。 (更糟的是,它并不一定甚至在随后的场合访问时表示相同的任意地址。)

gets(string[i]); 

嗯,这从标准输入读取数据的存储器的块开始于随机地址,再加上i*100 ,直到读取一个NUL字节。

不是很健壮。不保证会产生错误。如果你没有得到一个,那么随机地址必须映射到可写字节。

正如你看到的,我还没有分配的任何内存到各个串即,s[0]s[1]但令人惊讶的我的编译器并没有给我任何警告或错误,它完美的作品。

时间来减少您的期望或增加编译器的诊断级别。尝试-Wall -Wextra,如果它需要那种风格的选项。它应该警告你,string未经初始化就被使用。一个警告,gets已被弃用也是一个好主意,虽然我的编译器没有提到它。

C和C++允许您自己管理内存。您有责任验证指针。在C中,这是问题的主要来源。

在C++中,解决方案是使用指针的替代方法,例如引用(不能未初始化)和智能指针(为您管理内存)。虽然这个问题被标记为C++并编译为一个C++程序,但它不是以一种称为C++的样式编写的。

+0

感谢您的解释@potatoswatter。请帮助我理解最后一件事。据我所知*具有最低的优先级。所以我想我会声明一个char *并拥有一个大小为100的数组。这就是为什么我写了字符(*字符串)[100]。但你说它是指向一个由100个字符组成的字符串的指针。即使这似乎是一个非常愚蠢的问题,请给我解释一下。 –

+0

@SouravKanta:将*字符串放在圆括号内,以便优先。首先在括号内查找:“string是一个指针”,然后向右看“100个数组”然后看左边的“chars”。删除括号会改变含义。如果你在一个左侧开车的国家,就好像过马路一样,“向右看就走”。 – cdarke

+0

谢谢@cdarke, –

相关问题