3

char*最近、理解に大きな問題がありました。a を元に戻す再帰関数を作成したとchar*しますが、それを初期化する方法によってはアクセス違反が発生し、C++ の入門書では理解するための正しいパスが見つからなかったので、あなたの助けを求めています。

ケース 1 文字を入れ替えようとしたときにアクセス違反が発生した最初のケ​​ース:

char * bob = "hello";

CASE 2次に、これを試してみました

char * bob = new char[5];
bob[0] = 'h';
bob[1] = 'e';
bob[2] = 'l';
bob[3] = 'l';
bob[4] = 'o';

CASE 3しかし、その後、私がカウトをしたとき、最後にランダムながらくたが出たので、

char * bob = new char[6];
bob[0] = 'h';
bob[1] = 'e';
bob[2] = 'l';
bob[3] = 'l';
bob[4] = 'o';
bob[5] = '\0';

CASE 4それはうまくいったので、なぜこれがうまくいかないのかを自分に言い聞かせました

 char * bob = new char[6];
 bob = "hello\0";

CASE 5で失敗しました。次のようなことができるとどこかで読んだことがあります

char* bob[];

次に、それに何かを追加します。私の質問は、なぜ失敗するものと失敗しないものがあるのか​​、そしてそれを行う最善の方法は何ですか?

4

4 に答える 4

11

重要なのは、これらのポインターの一部が割り当てられたメモリ (読み取り/書き込み) を指しており、一部が文字列定数を指していることです。文字列定数は、割り当てられたメモリとは別の場所に格納され、変更できません。ほとんどの場合。多くの場合、システムの脆弱性はコードまたは定数が変更された結果として発生しますが、それは別の話です。

いずれにせよ、重要なのは new キーワードの使用です。これにより、読み取り/書き込みメモリにスペースが割り当てられるため、そのメモリを変更できます。

この発言は間違っている

char * bob = new char[6];
bob = "hello\0";

データをコピーせずにポインターを変更しているためです。あなたが欲しいのはこれです:

char * bob = new char[6];
strcpy(bob,"hello");

また

strncpy(bob,"hello",6);

"hello"文字列定数にはコンパイラによって null が配置されるため、ここでは nul は必要ありません。

于 2010-02-11T02:39:57.840 に答える
1
char * bob = "hello"; 

これは実際に次のように変換されます。

const char __hello[] = "hello";
char * bob = (char*) __hello;

次のように記述した場合、変更できません。

char * bob = "hello"; 
char * sam = "hello"; 

次のように翻訳できます。

const char __hello[] = "hello";
char * bob = (char*) __hello;
char * sam = (char*) __hello;

今、あなたが書くとき:

char * bob = new char[6];    
bob = "hello\0";

最初に 1 つの値を bob に割り当て、次に新しい値をそれに割り当てます。ここで本当にやりたいことは次のとおりです。

char * bob = new char[6];    
strcpy(bob, "hello");
于 2010-02-11T02:43:55.043 に答える
1

編集:質問は、もともとそこにあったが再タグ付けされたCではなく、C++として再タグ付けされました....

Ok。いくつかのことが混同されています... newCではなくC ++で使用されます。

  • ケース#1。それはcharへのポインタを宣言しています。文字列を操作できるはずです...文字を交換するために行ったコードを表示できますか。
  • ケース #2/#3。ランダムながらくたを取得し、ヌル ターミネータ、つまり '\0'... が、C/C++ の期間中、おそらく残りの人生で遭遇するすべての文字列を占めていることを発見しました...
+-+-+-+-+-+--+
|H|e|l|l|o|\0|
+-+-+-+-+-+--+
            ^
            | |
         ヌルターミネーター
  • コンパイル時に初期化される文字列を宣言するときに、 をstrcpy呼び出した後にそのような文字列を単純に割り当てることはできません。しかし、このようにすると、ポインタ変数にコピーされます。newchar *s = "foo";char *s = new char[6]; strcpy(s, "hello");s

最終的には、占有されているメモリ ブロックへのこのポインターsが簡単に上書きされ、バッファー オーバーフローを防ぐために注意する必要があることに気付くと、conniption の適合を誘発することがわかります... nul に関連するケース #3 を思い出してください。ターミネータ...実際には、文字列の長さは 5 ではなく 6 であることを忘れないでください。これは、nul ターミネータを考慮に入れているためです。

  • ケース#5。これは、char 型の配列、つまり多次元配列へのポインターを宣言することです。次のように考えてください。
*(ボブ​​ + 0) = "フー";
*(ボブ​​ + 1) = "バー";

消化しなければならないことがたくさんあることは承知しています...しかし、それ以上の考えを自由に投稿してください... :)そして、学習の幸運を祈ります...

于 2010-02-11T02:55:08.937 に答える
1

char const*文字列リテラルへのポインタ (二重引用符で囲まれたもの) には常に for を使用する必要があります。標準でも許可char*されていますが、文字列リテラルへの書き込みは許可されていません。GCC は、リテラル アドレスを に代入することに対してコンパイル警告を出しますchar*が、明らかに他のコンパイラではそうではありません。

于 2010-02-11T10:55:11.357 に答える