2017-11-10 3 views
-4

私はCでbegginnerですので、私と一緒にご負担ください。 私は*cまたはc[]という配列ステートメントを作成できることを知っています。Cのmemsetについての簡単な問題

私の質問はmemsetをについてです:

char str[] = "hello!"; 
    memset (str,'-',2); 
    puts (str); 

作品罰金。 しかし:

char *str = "hello!"; 
    memset (str,'-',2); 
    puts (str); 

いけない仕事、 は私がchar *str = ...は、通常の配列の文であることを知っています。

誰かが私にこの1つを助けることができれば私はありがとう!

+0

あなたの質問は、ポインタと配列に関して多くの人にお答えします。価値によるコピーやポインタによるコピー(他の人たちがそれをどのように呼び出すかを参考にする)のようなものについて考える。同じ概念がここで2つ起こります。 'char str =" hello ";'は、その配列の中でリテラル文字列 'hello'のコピーを作成し、内部でその文字列を操作できますが、' char * str = "hello"; 'そのリテラル文字列を指すポインタを扱い、 'C'ではそれらを読み書きしますが、書き込み/編集はできません。あなたは今、その違いを理解することを願っています。 – Michi

+0

* cは配列ステートメントではありません。 – Fredrik

答えて

5

ここでの違いは微妙です。文字列が格納される場所です。

char str[] = "hello!";はスタックに文字列を割り当てます。この文字列は更新できます。

char *str = "hello!";は、プログラムconstデータセグメントに文字列を割り当て、そのセグメントを指すようにstrを設定します。そのセグメントは操作できず、メモリアクセス違反でプログラムがクラッシュします。


現代のコンピュータは、複雑なメモリレイアウト、そしてあなたには、いくつかの時点で学習する必要があります概念のセット全体、などVirtual MemoryPaging となどStackHeapを持っています。

メモリにロードされているプログラムは、異なる権限で異なるページにロードされる異なるセクションに分割されます。コードとグローバルconst変数は、書き込み権限を持たないページ(読み込みのみ) - .textと.rodataの各セグメントに読み込まれますが、スタックとヒープは書き込むことができるが実行できないページに割り当てられます。データと.bss)。

第2の例のリテラル文字列 "hello"はconstセグメント(.rodata)に割り当てられているため、変更することはできません。あなたがその

char *s1 = "Hello!"; 
char *s2 = "Hello!"; 

のようないくつかの文字列を定義した場合また、それは実際の配列がスタックに割り当てられ、で満たされている第一の例では(アドレス比較!)

s1 == s2が真である可能性が非常に高いです"hello!\0"(7バイト)を含むバイト。そのメモリは、書き込み可能なページに割り当てられたスタック上にあるため、操作できます。

0
char str[] = "hello!"; 
    memset (str,'-',2); 
    puts (str); 

strが配列あるので、それが働いているとローカル配列は、我々は変更することができますRAMのスタック部に格納されているため、その内容は、あなたが変更することができます。

しかし

char *str = "hello!"; 
    memset (str,'-',2); // 

strはポインタスタック部に記憶されたSTR自体が、コードを指す(読み取り専用)は、Linuxの場合にはRAMのセクションあるため、それが働いていません。あなたは読取り専用メモリを変更しようとしています。なぜそれが動作しないのでしょうか?

+0

私は、 'str'は2番目のケースのcharポインタで、コードセクションアドレスで初期化され、コードセクションを変更するとアクセス違反が発生するとします。違いますか ? – achal

+0

Okみんな素早くrepplyしてくれてありがとう、申し訳ありませんが、それは私の悪い重複していた、神は皆さんを祝福; – Mondometal

関連する問題