プロが教える店舗&オフィスのセキュリティ対策術

1 #include <stdio.h>
2
3 void setstr(char *str){
4   str = "abc";
5   return;
6 }
7
8 int main(){
9
10   char *str;
11
12   setstr(str);
13
14   str[1] = 'E';
15
16   printf("str = %s\n", str);
17
18   return 0;
19 }
20


上記のプログラムの動きがいまいち理解できません。
(メモリの状態など)

16行目でprintfすると、結果は「str = 、E・」となります。

---まず、4行目でabcに対してメモリが確保されて、その先頭アドレスが
strに設定されます。

しかし、setstr関数を抜けた時点で、先ほど確保されたメモリは開放されて
しまう。(? ここは想像です。確証がありません)

main関数に戻ってきて、14行目で変更しているメモリは、abcがかつてあった
場所の"b"の部分。(str自体は何も変更されていないから)

16行目でprintfしているのだけど、なぜこの結果になるのかが分かりません。。

分かる方いましたら教えて下さい。上の文章では何を言っているのか分かりづらいとは
思いますが。。
説明には適宜行番号を使って頂いて構いません。
よろしくお願いします。

A 回答 (13件中11~13件)

ANo2です。


追記です。C言語は値渡しですから呼び出し先で引数(この場合はstr)に値を入れても、呼び出し元ではstrの内容は変更されていません。
void main()
{
char *str;
str = 0x00;
func(str);
}

void func(char *str)
{
str=0x01;
}

こう書いてもfuncの呼出し後のstrの値は0です。

void main()
{
char *str;
str = 0x00;
  *str = 0x30;
func(str);
}

void func(char *str)
{
*str=0x31;
}

これであればstrの指し示している内容は0x31に変更されます。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

ポインタ自身は、変更することができないが、
ポインタが指している先は変更することができるという
ことかな。。

お礼日時:2008/06/21 17:19

プログラムの意図はわかりますが、ポインタをリテラルのアドレスで初期化することは出来ません。


結局は、ANo1さんの言う通り14行目でメモリの内容を破壊しています。
    • good
    • 0

ひとまず setstr() の実装は忘れて、main の中だけ考えましょう。



char 型のポインタ変数 str を宣言していますが、str の指す先は存在していません。

setstr() は char型のポインタ変数を受け取りますが、それがどのような実装であろうと、
存在しないものを変更することはできません。

そして、str[1] = 'E'; で「存在しないはずのどこか」を破壊しています。
printf() ではその破壊された様子が見えているのです。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

strを宣言した時点では、NULLで初期化もしていないので、
何か不定値が入っているんですね、きっと、、

そしてその不定値をアドレスとして見て、そこらへん(不定値+1)の
メモリを書き換えてしまっているということですね。とてもシステムに
とって危険な香りがします。。

お礼日時:2008/06/21 17:13

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!