2011-12-29 1 views
4

私はCのコースを読んでいます(それはおそらくあなたが知らないでしょう)。文字列の動作を理解するための小さな練習があります。そのため私はエクササイズを開始するための小さなCプログラムを作成しましたが、私のプログラムの最初の出力は(私にとって)驚くべきものです。Cの文字列の動作

私のCプログラムのソース:

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

void printString(char *string) 
{ 
    printf("0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19\n"); 
    printf("%c ",string[0]); 
    printf("%c ",string[1]); 
    printf("%c ",string[2]); 
    printf("%c ",string[3]); 
    printf("%c ",string[4]); 
    printf("%c ",string[5]); 
    printf("%c ",string[6]); 
    printf("%c ",string[7]); 
    printf("%c ",string[8]); 
    printf("%c ",string[9]); 
    printf("%c ",string[10]); 
    printf("%c ",string[11]); 
    printf("%c ",string[12]); 
    printf("%c ",string[13]); 
    printf("%c ",string[14]); 
    printf("%c ",string[15]); 
    printf("%c ",string[16]); 
    printf("%d ",string[17]); 
    printf("%d ",string[18]); 
    printf("%d\n",string[19]); 
} 

void main(){ 

    char str[20]; 

    strcpy(str,"Dag grootmoeder!"); 
    printString(str); 
} 

Iのgcc(特別なスイッチ)でコンパイルされたプログラムを実行したいくつかの回: (英語を話す人Dag grootmoeder! == Hi grandma!用)

ここ
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 

D a g g r o o t m o e d e r ! 94 -90 111 

$./oefString 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 

D a g g r o o t m o e d e r ! 51 -12 96 

$./oefString 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 

D a g g r o o t m o e d e r ! -17 -117 28 

$./oefString 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 

D a g g r o o t m o e d e r ! 96 15 -28 

$./oefString 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 

D a g g r o o t m o e d e r ! -20 -46 -18 

$./oefString 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 

D a g g r o o t m o e d e r ! 68 -75 58 

1)strの最後の3つのインデックスのゴミ値を取得するのはなぜですか?最初はprintf()で、%cと入力し、文字が変更されていることに気がついたので、それ以降は整数値を表示するために%dを使用しました。

2)これらの値はなぜ変わるのですか?私は何もしないで、同じ文字列をstrcpy()をstrにコピーします。

返信するには時間がかかり、応答した人にはさらに高価なThx!

ジョーン

答えて

7

あなたは、単に文字列の終わりを越えメモリをアクセスしてるしています。あなたは何かを見つけることができるように、あなたはそれを記入しませんでした。

"文字列"は実際には0-終了した配列(またはメモリへのポインタ)です。したがって、"%d"を使用して文字を印刷すると、!の直後の最後の要素が0になります。

あなたはそれが予測可能になりたい場合は、あなたがそれを使用する前に、文字列を初期化することができます側の注意点として

または

char str[20] = {0,}; 

を、それがint main、ないvoid mainです。

+0

*私は実際にメモリを見ていると思ったが、char str [20]の初期化で20バイトを予約している。 (または私は仮定する)。 予約されている20バイトの未使用メモリを埋めるのにいくつかのメモリ最適化はありますか? –

+0

thx、スタック無作為化を無効にしたときに気付いたこれらの値は同じままです。 "0">/proc/sys/kernel/randomize_va_space –

+0

@JornDePrilあなたの配列を初期化しない場合、あなたのサイドノートについて – cnicutar

0
char str[20]; 
... 
strcpy(str,"Dag grootmoeder!"); 

strがランダムな値(存在RAMを使用した最後の時間だったものは何でも) 今、あなたはそこ初期(ランダム)値に最後の3つの文字を残して、その中に16バイトの文字列をコピーするので、これらはで始まります

0

ブロックスコープで定義されたオブジェクトで、ストレージクラス指定子(たとえば、strの配列オブジェクト)がない場合、自動保存期間があります。

明示的に初期化されていない自動オブジェクトは不定値です。したがって、あなたのstrオブジェクト宣言の後、すべての配列要素は不確定な値を持ちます。文字列"Dag grootmoeder!"を配列にコピーすると、最初の17文字(文字列の長さ+末尾のヌル文字)の要素が指定された値になります。これにより、配列の最後の3つの要素が不確定な値になります。

Cでは、不定値が指定されていないか、トラップ表現であると言われています。また、不確定な値を読み取ることは未定義の振る舞いであるため、未定義の振る舞いを持つ通常どおり、これを行うときにはゴミを出すなど何かが起こる可能性があります。