3

重複の可能性:
C の char s[] と char *s の違いは何ですか?

何かを修正しようとするのではなく、一般的な質問のほうが多いので、私は C プログラミング言語の本を読んでいます。

char amessage[] = "blah";
char *pmessage = "blah";

1 つは char 配列であり、もう 1 つは文字列定数へのポインターです。彼らは char 配列を変更することは許容できると言いますが、未定義の動作を引き起こすため、文字列定数を変更しないでください。私の質問は次のとおりです。文字列定数は、char配列と同じようにメモリに格納されていませんか? なぜ私はそれを次のように変更できますか

char *p = "this is a string constant";
*(p+2) = 'a';
printf("%s", p);

ご想像のとおり、「これは文字列定数です」と出力されます。文字列定数は実行時に変更されるべきではないので、それがどのように理にかなっているのか理解できます。なぜなら、コードに取り組んでいる他の人/自分自身が、その値が変更されることを期待していないことを混乱させる可能性があるからです。 、トリガーされる可能性のある未定義の動作は何ですか?また、char配列がトリガーしない場合に、どのように機械的に逆火する可能性がありますか? 文字列定数がメモリ内でどのように機能し、コンパイラによってどのように認識されるかについて、何かが欠けているのではないかと思っています。

4

3 に答える 3

4

少なくとも私のコンピューターでは、次のプログラムがクラッシュします。

#include <stdio.h>
int main() { 
  char *p = "this is a string constant";
  *(p+2) = 'a';
  printf("%s", p);
}

うまくいっているように見える場合 (特定の組み込みコンパイラではそうかもしれません)、運が良かっただけです。未定義の動作は、プログラムが何でもできることを意味します。http://blog.regehr.org/archives/213を参照してください。

char s[] と char *s の違いは何ですか?も参照してください。.

于 2011-05-12T03:21:37.437 に答える
1

char 配列の場合、文字列リテラルの内容"blah"もスタックにコピーされます。したがって、UB を呼び出さずに変更できます。結局のところ、単なるコピーだからです。

実際に元の文字列リテラルを変更しようとする場合はchar *、標準の UB に従ってください。

于 2011-05-12T03:13:38.047 に答える
0

文字列定数では、データが格納される場所についての保証はありません。コンパイラは、書き込みが禁止されているはずなので、必要なトリックを自由に実行できます。そのため、たとえば、ポインターが実際に読み込まれた実行可能コード自体の文字列定数が定義されている場所を指していることは前代未聞ではありません。

于 2011-05-12T03:20:12.310 に答える