7

cプログラミングブックには、printfを使用して文字列を印刷するには、文字列をnullで終了する必要があると書かれていますが、次のプログラムでは、nullで終了していないにもかかわらず、文字列を印刷します。

#include <stdio.h>
#include <stdlib.h>

int main(){
    int i ;
    char str[10] ;
    for(i = 0 ; i < 10 ; i++ ) {
        str[i] = (char)(i+97) ;
    }

    printf("%s",str) ;
}

私はコードブロックIDEを使用しています。

4

5 に答える 5

10

配列の境界を超えて読み取ることは未定義の動作です。実際には、クラッシュしなかったのは不運でした。十分な回数実行したり、関数で呼び出したりすると、クラッシュする(またはしない)場合は、常に文字列を終了する必要があります。または幅指定子を使用します。

printf("%.10s", str);
于 2012-12-01T04:38:58.113 に答える
5

の10番目の要素の後にあるものはstrすべてnullになります。そのnullは配列の定義された境界の外側にありますが、Cには配列の境界チェックがありません。それがうまくいったのはあなたの場合の幸運です。

于 2012-12-01T04:37:06.090 に答える
1

C標準によれば、printf関数は、ヌル文字が見つかるまで文字列内の文字を出力します。それ以外の場合、定義された配列インデックスの後に、それが何をするかは定義されません。私はあなたのコードをテストしました。「abcdefghij」を出力すると、ガベージ値が出力されます。

于 2012-12-01T04:44:38.290 に答える
1

その呼び出しの前に他のことを行うと、スタック領域には未使用のデータ以外のデータが含まれます。想像してみろ:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int use_stack(void) {
   char str[500];
   memset(str, 'X', sizeof(str));
   printf("Filled memory from %p to %p.\n", &str, &str+sizeof str);
}

void print_stuff() {
    int i;
    char str[16]; // changed that so that 10..15 contain X
    for(i = 0; i < 10; i++) {
        str[i] = (char)(i+97);
    }

    printf("%s<END>",str); // have a line break before <END>? Then it comes from i.
    printf("&str: %p\n", &str);
    printf("&i: %p\n", &i);
    // Here you see that i follows str as &i is &str + 16 (0x10 in hex)
}

int main() {
    use_stack();
    print_stuff();
}

スタック領域はXesでいっぱいになり、printf()それらが表示されます。

あなたの状況とあなたの環境では、スタックはプログラムの開始時に偶然に「クリーン」です。

編集:これは起こるかもしれないし、起こらないかもしれない。コンパイラが変数iを配列の直後に配置した場合でもNUL、最初のバイトはの値であるため、データは終了iします(これも出力されます-あなたの場合はlibneブレークである可能性があります-そして2番目のバイトはNULバイトです。これが当てはまる場合でも、コードはUB(未定義の動作)を呼び出します。

出力に文字hexdumpが含まれているかどうかを(プログラム出力をパイプでつなぐなどして)確認できますか?0Aもしそうなら、私の推測は正しいです。私はちょうどそれをテストしました、私のコンパイラ(gcc)でそれは方法のようです。

言ったように、あなたが頼るべきものは何もありません。

EDIT2:前に改行が表示された場合<END>、私の推測は正しかった。そして、現在印刷されているポインタを見ると、メモリ内のそれらのアドレスを比較できます。

于 2012-12-01T05:57:40.990 に答える
0

デバッグモードで*(str+10)は、未使用のスペース全体の初期値が「0」であるため、0で終了しているように見えます。

bash-3.2$ clang -O0 t.c -o t #compile in debug mode
bash-3.2$ ./t
abcdefghij
bash-3.2$ clang -O2 t.c -o t #compile with optimization
bash-3.2$ ./t
abcdefghij2÷d=
于 2012-12-01T04:37:23.240 に答える