为啥会发生这种情况(见图)?

Posted

技术标签:

【中文标题】为啥会发生这种情况(见图)?【英文标题】:why does this happen (see image)?为什么会发生这种情况(见图)? 【发布时间】:2010-09-22 04:52:07 【问题描述】:

为什么以下内容会产生效果 - 它会打印一个充满随机字符的终端,然后退出并留下一个命令提示符,当您输入它时会产生垃圾。 (我尝试过是因为我认为它会产生段错误)。

#include <stdio.h>

int main()
    char* s = "lololololololol";
    while(1)
        printf("%c", *s);
        s++;
    

编译时使用:

gcc -std=c99 hello.c

【问题讨论】:

顺便说一下,如果您使用的是 *nix 系统,通常可以使用“stty sane”将终端重置为可用状态,尽管您必须盲目输入。 对于 Linux 控制台,你可以做 echo c 即使看不到也可以输入“reset”,这对很多人都有效。 【参考方案1】:

它最终会出现段错误,但在此之前它会打印出同一页面中的任何字节。这就是您在屏幕上看到随机字符的原因。

这些很可能包括转义序列以更改(例如)控制台的字符编码。这就是为什么您在控制台退出后在控制台上键入时也会出现乱码。

【讨论】:

这可能也是他认为它退出而不是段错误的原因 - “Segmentation fault”消息本身也变成了胡言乱语。【参考方案2】:

因为您有一个无限循环 (while(1)),并且您不断获取指针 (*s) 的当前值,然后将指针向前移动一个字符 (s++)。这样做的效果是远远超过字符串的末尾进入“垃圾”(未初始化的内存),结果会打印到控制台。

【讨论】:

【参考方案3】:

除了其他人所说的关于您忽略字符串终端字符并随意打印字符串后内存中的内容之外,您的命令提示符也是“垃圾”的原因是通过打印特定的“ unprintable" 字符,您的终端会话处于奇怪的字符模式。 (我不知道它是哪个角色,也不知道它做了什么模式改变,但也许其他人比我更了解它。)

【讨论】:

当然,这完全取决于他使用的终端仿真。我认为 Xterm 默认为 DEC VT-220 模式。以下是该模式的终端控制代码的部分列表:connectrf.com/Documents/vt220.htmllists【参考方案4】:

您只是打印出内存中的内容,因为您的循环不会在字符串的末尾停止。每个随机字节都被解释为一个字符。当您到达内存页面的末尾(并进入不可读的区域)时,它将出现段错误。

【讨论】:

【参考方案5】:

稍微扩展这里给出的答案(都非常好)......当我刚开始使用 C 时,我自己不止一次遇到过这个问题,这是一个很容易犯的错误。

快速调整您的while 循环将修复它。其他人都给了你原因,我会告诉你方法:

#include <stdio.h>

int main() 
    char *s = "lolololololololol";
    while (*s != '\0') 
        printf("%c", *s);
        s++;
    

请注意,我们不是无限循环 (while(1)),而是进行循环检查,以确保我们正在拉取的指针不是字符串的空终止符,从而避免了溢出相遇。

如果您完全需要while(1)(例如,如果这是家庭作业并且教师希望您使用它),请使用break 关键字退出循环。以下代码有异味,至少对我而言,但它有效:

#include <stdio.h>

int main() 
    char *s = "lolololololololol";
    while (1) 
        if (*s == '\0')
            break;
        printf("%c", *s);
        s++;
    

两者都产生相同的控制台输出,最后没有换行符:

呵呵呵呵呵呵呵呵

【讨论】:

【参考方案6】:

您的循环不会终止,因此 println 会在您写入文本之后打印内存中的任何内容;最终它会访问它不允许读取的内存,导致它出现段错误。

您可以按照其他人的建议更改循环,或者您可以利用在 c 中零为假且 null(终止所有字符串)也为零的事实,因此您可以将循环构造为:

while (*s) 

而不是:

while (*s != '\0')

第一个可能比较难理解,但它确实有简洁的优点,所以经常被用来节省一点打字。

【讨论】:

【参考方案7】:

此外,您通常可以使用“reset”命令返回命令提示符,当然是盲目输入。 (输入、重置、回车)

【讨论】:

以上是关于为啥会发生这种情况(见图)?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在浮点转换中会发生这种情况?

如果二维数组不是双指针,那么为啥会发生这种情况?

如果 Java 是一种“按值调用”语言,那么为啥会发生这种情况?

已与其底层 RCW 分离的 COM 对象无法使用 - 为啥会发生这种情况?

为啥当objective-c 有冲突返回类型时会发生这种情况?

“应用程序无法启动,因为找不到 cxcore210.dll”。为啥会发生这种情况?