6

次のような効果があるのはなぜですか?ランダムな文字でいっぱいの端末を出力し、入力するとゴミが生成されるコマンド プロンプトを残して終了します。(セグフォルトになると思ったのでやってみました)。

http://oi38.tinypic.com/r9qxbt.jpg

#include <stdio.h>

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

それは次のようにコンパイルされました:

gcc -std=c99 hello.c
4

7 に答える 7

20

最終的にはセグメンテーション違反が発生しますが、その前に、同じページにあるバイトがすべて出力されます。そのため、画面にランダムな文字が表示されます。

これらには、コンソールの文字エンコードを変更するためのエスケープシーケンスが含まれている場合があります。そのため、コンソールを終了した後でコンソールに入力すると、ぎこちなくなります。

于 2008-11-13T17:31:14.617 に答える
7

ループは文字列の最後で停止しないため、メモリ内にあるものを出力しているだけです。各ランダムバイトは文字として解釈されます。メモリページの最後に到達すると(そして読み取り不能な領域に入ると)、セグメンテーションフォールトが発生します。

于 2008-11-13T17:28:11.487 に答える
7

無限ループ(while(1))があり、ポインタの現在の値()を取得し続け*s、ポインタを1文字前方(s++)に移動するためです。これには、文字列の終わりをはるかに超えて「ガベージ」(初期化されていないメモリ)に移動する効果があり、その結果、コンソールに出力されます。

于 2008-11-13T17:29:11.610 に答える
7

文字列の終端文字を無視し、文字列を過ぎてメモリにあるものを意地悪に印刷することに関して他の誰もが言ったことに加えて、コマンドプロンプトも「ガベージ」である理由は、特定の「印刷できない」文字を印刷することによるものです、端末セッションが奇妙な文字モードのままになっています。(それがどのキャラクターなのか、どのモード変更を行うのかはわかりませんが、私よりもよく知っている他の誰かがそれについてパイプできるかもしれません。)

于 2008-11-13T17:37:52.950 に答える
2

ここで与えられた答えを少しだけ拡張します(すべて優れています)... Cを始めたばかりのときに、これに何度も遭遇しましたが、それは簡単な間違いです。

ループを簡単に調整するwhileと修正されます。他の誰もが理由を教えてくれました。

#include <stdio.h>

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

無限ループ ( while(1)) の代わりに、プルしているポインターが文字列の null ターミネーターではないことを確認するためにループ チェックを行っていることに注意してください。これにより、発生しているオーバーランが回避されます。

絶対に必要な場合while(1)(たとえば、これが宿題であり、インストラクターが使用を求めている場合) は、breakキーワードを使用してループを終了します。次のコードは、少なくとも私にはにおいがしますが、機能します。

#include <stdio.h>

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

どちらも同じコンソール出力を生成しますが、最後に改行はありません。

ロロロロロロロル

于 2008-11-13T18:43:30.463 に答える
1

ループは終了しないため、println は、記述したテキストの後にメモリ内にあるものをすべて出力します。最終的に、読み取りが許可されていないメモリにアクセスし、セグメンテーション違反を引き起こします。

他の人が提案したようにループを変更するか、c ではゼロが false で、null (すべての文字列を終了する) もゼロであるという事実を利用できるため、ループを次のように構築できます。

while (*s) {

それよりも:

while (*s != '\0')

最初のものは理解するのがより難しいかもしれませんが、簡潔であるという利点があるため、タイピングを少し節約するためによく使用されます。

于 2008-11-18T21:04:53.420 に答える
0

また、通常は「reset」コマンドを使用してコマンドプロンプトに戻ることができますが、もちろん盲目的に入力します。(Enter、reset、Enterと入力します)

于 2008-12-02T21:16:02.037 に答える