5

私は理解しましたが、私は過去数時間問題に悩まされてきました。これが私の問題です:

void cut_str(char* entry, int offset) {
    strcpy(entry, entry + offset);
}

char  works[128] = "example1\0";
char* doesnt = "example2\0";

printf("output:\n");

cut_str(works, 2);
printf("%s\n", works);

cut_str(doesnt, 2);
printf("%s\n", doesnt);

// output:
// ample1
// Segmentation: fault

ここに来ていないchar*/char[]について何か重要なことがあるように感じます。

4

3 に答える 3

11

違いはdoesnt、文字列定数に属するメモリを指しているため、書き込みができないことです。

あなたがこれをするとき

char  works[128] = "example1\0";

コンパイラは、書き込み不可能な文字列の内容を書き込み可能な配列にコピーします。\0ちなみに、必須ではありません。

ただし、これを行うと

char* doesnt = "example2\0";

コンパイラーは、書き込み不可能なメモリー領域を指すポインターを残します。繰り返し\0ますが、コンパイラによって挿入されます。

を使用している場合は、文字列リテラルを使用しgccて書き込み可能を初期化することについて警告することができます。char *オプションは-Wwrite-stringsです。次のような警告が表示されます。

 warning: initialization discards qualifiers from pointer target type

ポインタを宣言する適切な方法doesntは次のとおりです。

const char* doesnt = "example2\0";
于 2012-06-29T01:20:02.230 に答える
4

タイプchar[]char *は非常に似ているので、あなたはそれについて正しいです. 違いは、型のオブジェクトが初期化されるときに何が起こるかにあります。worksタイプのオブジェクトにchar[]は、スタック上に割り当てられた 128 バイトの変数ストレージがあります。doesntタイプ のオブジェクト にはchar *、スタックにストレージがありません。

文字列が格納される正確な場所doesntは C 標準では指定されていませんが、プログラムが実行のためにロードされるときにロードされる変更不可能なデータ セグメントに格納される可能性が最も高いです。これは変数ストレージではありません。したがって、変更しようとするとセグメンテーション違反が発生します。

于 2012-06-29T01:25:24.333 に答える
3

これにより、スタックに128バイトが割り当てられ、その名前worksを使用してそのアドレスを参照します。

char works[128];

works書き込み可能なメモリへのポインタもそうです。

これにより、読み取り専用メモリにある文字列リテラルが作成され、その名前doesntを使用してそのアドレスが参照されます。

char * doesnt = "example2\0";

works書き込み可能なメモリを指しているため、にデータを書き込むことができます。doesnt読み取り専用メモリを指しているため、にデータを書き込むことはできません。

"\0"また、すべての文字列リテラルは暗黙的に文字列の最後にゼロバイトを追加するため、文字列リテラルをで終了する必要はないことに注意してください。

于 2012-06-29T01:23:43.563 に答える