【问题标题】: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”,这对很多人都有效。

标签: c console terminal 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”命令返回命令提示符,当然是盲目输入。 (输入、重置、回车)

          【讨论】:

            猜你喜欢
            • 2021-01-24
            • 1970-01-01
            • 2021-04-30
            • 1970-01-01
            • 2018-04-27
            • 2013-08-02
            • 2018-12-19
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多