0

次のように宣言して実行すると、セグメンテーション違反が発生します。

main()
{
    char *p = "boa";
    *(p+1) = 'y';
    printf("%s",p);
}

char *p定数などだと思います。

ただし、以下は正常に機能します。

main()
{
    int i = 300;
    char *p = (char*)&i;
    *(p+1) = 'y';
    printf("%s",p);
}

この背後にある理由は何ですか?上記のルールはこれにも当てはまりませんか?

4

3 に答える 3

3

それはあなたの「うまくいく」の定義に依存します。しかし、割り当てがセグメンテーション違反にならない理由はp、変数のアドレスを指すように作成されたためiです。これは明らかに定数ではありません。i定数値が割り当てられましたが、iそれ自体は定数ではありません。

i = 300(リトルエンディアンx86を想定)の場合:

  +--+--+--+--+
i:|2c|01|00|00|
  +--+--+--+--+
  .
 /|\
  |

p:&i

*(p+1) = 'y'

  +--+--+--+--+
i:|2c|79|00|00|
  +--+--+--+--+
  .
 /|\
  |

p:&i

したがって、printステートメントはたまたま印刷,yされますが、これはプラットフォームのバイト順序に依存しているためです(これ2cは印刷可能なASCII文字でした)。ビッグエンディアンのマシンでは、または非ASCIIの場合は、状況が異なる可能性があります。

于 2012-07-28T08:34:48.570 に答える
1

ああ少年...

最初の1つは、文字列が存在するためにセグメンテーション違反が発生しますconst(あなたはその権利を持っています)。ただし、2つ目は、ポインターのセマンティクスの魅力的な乱用です。;-)

2番目の例で行っていることは次のとおりです。

  • 値を持つ乱数を持ってintいる(あなたの場合- 300
  • そのアドレスを取得しますint-基本的には300の(32ビット?)を保持する場所へのアドレスであり、各要素が8ビット値を指すにintキャストしますchar*
  • 「最初の」8ビット値のアドレスを取得し、1ずつインクリメント(8ビットずつインクリメント(!))、それらの8ビットの値を数値ASCIIコード「y」に変更します。
  • 「結果の文字列」を印刷します
于 2012-07-28T08:36:37.153 に答える
1

違いは次のとおりです。

char *p="boa";

pポインターです。変更できないp文字列リテラルを指摘しており、変更しようとするとセグメンテーション違反が発生します。"boa"

int i=300;
char *p=(char*)&i;

iはタイプ の変数ですint。定数300を使用して初期化し、 の値をの場所にiビットごとにコピーしますが、定数自体を指すことはなく、初期化子として使用するだけですこれが違いです。最初の例では定数文字列リテラルを指していますが、2 番目の例では type の変数を指しています。したがって、非定数オブジェクトを変更しているため、後でポインターを使用しての場所を変更しても問題ありません。300ipintipi

于 2012-07-28T08:41:31.613 に答える