OKWAVEのAI「あい」が美容・健康の悩みに最適な回答をご提案!
-PR-
解決
済み

char*型が0x0を含む場合

  • 暇なときにでも
  • 質問No.238677
  • 閲覧数568
  • ありがとう数4
  • 気になる数0
  • 回答数7
  • コメント数0

お礼率 59% (194/328)

char *str = {0x61, 0x62, 0x0, 0x64};

ができないから、

char *str = "abcd";
str[2] = 0;

として、{0x61, 0x62, 0x0, 0x64} という文字列を作ってみた。

このポインタ str は解放する必要がない。
malloc( ) で確保したなら free( ) する必用がある。
普通のポインタは、もしかしたら 0x0 までしか
確保されていないのかなと思いました。

この場合では、str[3] == 0x64 だという結果になったけど、
それは str[2] の次のデータが 0x64 だったわけで、
str[2] に 0x0 が入った時点で、str[3] 以降の領域は
str とは無関係かもしれないと思いました。

つまり、char*型は、0x0 までの部分だけを確保し、
この例のソースでは、str[3] 以降の領域は確保されていないから
後で、知らないうちに値が変わっている可能性がある。

という想像をしてみたけど、あってますか?
通報する
  • 回答数7
  • 気になる
    質問をブックマークします。
    マイページでまとめて確認できます。

質問者が選んだベストアンサー

  • 回答No.1
レベル13

ベストアンサー率 37% (331/872)

こんにちは、honiyonです。

 ハズレです。
 最初に 4byte確保したなら、str[2] = NULL; としても 4byte確保されています。
 char*型はあくまで「char型へのポインタ」であり、メモリの操作は行いません。

 0x00 も立派な「データ」ですよ。

 char* = 文字列データ という意味合いが強いですが、あくまで char型は「0~255の整数型」であり、それ以外の用途にも使用される事があります。 char* でメモリを確保し、バイナリデータを扱う事だって出来ます。

 参考になれば幸いです(..
お礼コメント
A__

お礼率 59% (194/328)

ありがとうございます。
ハズレでしたか。

メモリの操作は行わないという意味が分かりませんでした。

char *str = "abcd";
で5バイト確保される。
そして str を使う。
必要なくなったら、確保した5バイトを解放したい。
解放したい場合はどうしたらいいんですか?

char *str = "abcd";
printf("%x,%x,%x,%x,%x\n", str[0], str[1], str[2], str[3], str[4], str[5]);
str = "de";
printf("%x,%x,%x,%x,%x\n", str[0], str[1], str[2], str[3], str[4], str[5]);

結果は
61, 62, 63, 64, 0
64, 65, 0, 25, 23

この時、str が確保しているのはまだ5バイトですか?

char *str = "abcd";
の後に
str = "de";
としました。
どこかのサイトで、ポインタの値を書き替えてはいけない
と書いてあったのを見たような記憶があります。
この結果は企画にない結果だったんですか?

char *str;
で宣言したポインタに大きなサイズのデータを格納した場合、
プログラムが終了するまで、その大きなサイズを確保しているのは
よくないことだから解放したいと思って質問しました。
投稿日時 - 2002-03-21 19:35:53
-PR-
-PR-

その他の回答 (全6件)

  • 回答No.3
レベル12

ベストアンサー率 75% (398/526)

# 何か、メモリとポインタ変数との間に、変な誤解を持たれているようですが・・・ 「文字列」というのは、確保されるものではありません。例えば、   char *str = "abcd"; とすると、コンパイルした時点で、プログラム内部のどこかに 0x61, 0x62, 0x63, 0x64, 0x00(全部で5バイト)が用意されます。(文字列の最後には、'\0� ...続きを読む
# 何か、メモリとポインタ変数との間に、変な誤解を持たれているようですが・・・

「文字列」というのは、確保されるものではありません。例えば、
  char *str = "abcd";
とすると、コンパイルした時点で、プログラム内部のどこかに 0x61, 0x62, 0x63, 0x64, 0x00(全部で5バイト)が用意されます。(文字列の最後には、'\0'が付加されることをお忘れなく!)
この「用意」というのは、「プログラム実行時にメモリを確保してデータが配置される」のではなく、「コンパイルされたプログラムに、その一部として既に存在している」ということです。
ソース名が hoge.c だとすれば、hoge.exe の中には、"abcd" が含まれているのです。

(つまり)文字列はプログラムの一部なので、プログラムがメモリ上にロードされた時点でアドレスが決定されます。"文字列" は、そのアドレスを持っています。

関数内で宣言された char * 型の str は、スタックメモリ上に確保されます。無論、確保されるサイズは4バイトです。
str = "abcd" となっているので、str の確保されている4バイトの領域に、"abcd" が存在するメモリのアドレスが代入されます。
プログラム実行時に行われるのは、たったこれだけです。
つまり、ポインタ変数 str と、"abcd" が存在するメモリの間には、そのアドレスを知っていること以外、何の関係もないのです。

alloc系関数を用いた動的メモリ確保の場合も同じです。
malloc は必要サイズのメモリを確保し、その先頭アドレスを返します。
→これをポインタ変数で受け取るのは、メモリにアクセスするのに必要だからであって、このポインタにメモリを割り当てるわけではありません。
次にこのメモリ領域を解放する場合、malloc が返したアドレスを使って、free が解放処理を行います。
→無論アドレスを受け取ったポインタ変数を解放するわけではありません。ポインタ変数を介して、確保したメモリのアドレスを free に知らせるだけです。
(ですので「ポインタを解放する」という表現は、明らかに正しくありません。)

話を質問に戻しますが、文字列 "abcd" が存在していた5バイトの領域が、勝手に使用されてしまうことはありません。
意図的に str[2] = 0 ('\0'であるべき) としても、その5バイトの領域の内容が 0x61, 0x62, 0x00, 0x63, 0x00 になるだけであって、解放とかそういう次元の話は、全く関係ありません。
表示した時に「ab」しか表示されないだけであって、
  str[2] = 'Z';
とすれば、「abZd」が、いつでも必ず表示されます。


  • 回答No.2
レベル9

ベストアンサー率 33% (33/98)

> このポインタ str は解放する必要がない。 むしろ、解放したらまずいです。 たぶん。判断されたのは printfで表示しても abしか出なかったからだと思いますが、これは\0(0x00)がCに置ける文字列の終わりを示すコードになっているからです。 もし、確保されていなければ、str[3]のアクセス時に不正終了しかねません。「確保されていないメモリ」にアクセスするわけですから。
> このポインタ str は解放する必要がない。
むしろ、解放したらまずいです。

たぶん。判断されたのは
printfで表示しても
abしか出なかったからだと思いますが、これは\0(0x00)がCに置ける文字列の終わりを示すコードになっているからです。

もし、確保されていなければ、str[3]のアクセス時に不正終了しかねません。「確保されていないメモリ」にアクセスするわけですから。
  • 回答No.4
レベル12

ベストアンサー率 40% (230/562)

おもしろい発想です。 C言語勉強し始めの頃は、こんな疑問に大いにぶつかってください。 今回は、皆様の言うとおり、はずれですが。 おまけ情報です。 char*はCスタイルの文字列と呼ばれますが、これは\0(0x00)までを文字範囲とする、という規定の基に、様々な操作がなされます。 確保した領域の中に\0が見つからなければ、文字列操作関数は、確保してある領域を超え、一般保護違反というエラーが発生 ...続きを読む
おもしろい発想です。
C言語勉強し始めの頃は、こんな疑問に大いにぶつかってください。
今回は、皆様の言うとおり、はずれですが。

おまけ情報です。
char*はCスタイルの文字列と呼ばれますが、これは\0(0x00)までを文字範囲とする、という規定の基に、様々な操作がなされます。
確保した領域の中に\0が見つからなければ、文字列操作関数は、確保してある領域を超え、一般保護違反というエラーが発生する危険性を秘めます。

VBやJAVA、Perlの文字列は、\0で終わるという保証はなく、わざわざこの文字列は何文字あるという情報と一緒に、変数を管理します。
でも、これによって\0を途中に含む文字列が作れますし、確保した範囲を超えてアクセスする危険性も低くなります。

ポインタマニアの、はぽるんでした。
お礼コメント
A__

お礼率 59% (194/328)

ありがとうございます。
投稿日時 - 2002-07-14 09:17:31
  • 回答No.5
レベル6

ベストアンサー率 40% (4/10)

最近 C 言語をやっていないので懐かしいです。 char *str[] = {0x61, 0x0, 0x64}; なんていう宣言もありですね。 みなさんの回答でちょっと気になった点を。 (あくまで char型は「0~255の整数型」) signed か unsigned は処理系次第ではなかったでしたっけ。 (関数内で宣言された char * 型の str は、スタックメモリ上に確 ...続きを読む
最近 C 言語をやっていないので懐かしいです。
char *str[] = {0x61, 0x0, 0x64};
なんていう宣言もありですね。

みなさんの回答でちょっと気になった点を。

(あくまで char型は「0~255の整数型」)
signed か unsigned は処理系次第ではなかったでしたっけ。

(関数内で宣言された char * 型の str は、スタックメモリ上に確保されます。無論、確保されるサイズは4バイトです。)
4バイトというのと、スタックに確保されるというのも、処理系次第ですよね。
最適化するとレジスタを使ってしまったりする事も。

なんんだかややこしい話ですね・・・
  • 回答No.6
レベル12

ベストアンサー率 75% (398/526)

No.5 の方が「処理系依存」のことについて触れられていますが、それについてちょっとアドバイスを。 >signed か unsigned は処理系次第ではなかったでしたっけ。 >4バイトというのと、スタックに確保されるというのも、処理系次第ですよね。  最適化するとレジスタを使ってしまったりする事も。 どちらも確かにその通りです。 でも A__ さんに理解して欲しいのは、 >char ...続きを読む
No.5 の方が「処理系依存」のことについて触れられていますが、それについてちょっとアドバイスを。

>signed か unsigned は処理系次第ではなかったでしたっけ。
>4バイトというのと、スタックに確保されるというのも、処理系次第ですよね。
 最適化するとレジスタを使ってしまったりする事も。

どちらも確かにその通りです。
でも A__ さんに理解して欲しいのは、
>char * 型は、文字列処理以外にも使用される、ということ
>ポインタ変数と文字列アドレスの関係について
という部分です。
(それを説明するには、どちらも十分な説明だったと思いますが。)

また、私はこの質問を、ポインタ変数を文字列で初期化した場合の、メモリとの関係について尋ねられているものだと思いました。
だとすれば、
> char *str[] = {0x61, 0x0, 0x64};
これでは文字列は生成されませんので、注意が必要です。
この記述では、それぞれのデータをアドレスとするポインタの配列ができるだけです。もちろん操作すると大変危険です。
  • 回答No.7
レベル6

ベストアンサー率 40% (4/10)

> char *str[] = {0x61, 0x0, 0x64}; 失礼しました。私のタイプミスです(笑) ご指摘ありがとうございました。 *はいらないですね。 > char str[] = {0x61, 0x0, 0x64}; 回答はみなさんの答えで的を得ています。 質問者がの処理系が違っていた場合には記述の曖昧さで悩んでしまうと可哀想かなと思ったので補足をしてみました。余 ...続きを読む
> char *str[] = {0x61, 0x0, 0x64};
失礼しました。私のタイプミスです(笑)
ご指摘ありがとうございました。
*はいらないですね。
> char str[] = {0x61, 0x0, 0x64};

回答はみなさんの答えで的を得ています。
質問者がの処理系が違っていた場合には記述の曖昧さで悩んでしまうと可哀想かなと思ったので補足をしてみました。余計でしたら申し訳ないです。
そういう自分が上記のようなタイプミスしているくらいですから、私自身もまだまだ甘いですね。ただのタイプミスといえど挙動はかなり違いますからね。
このQ&Aのテーマ
このQ&Aで解決しましたか?
-PR-
-PR-
こんな書き方もあるよ!この情報は知ってる?あなたの知識を教えて!
このQ&Aにはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。

その他の関連するQ&A、テーマをキーワードで探す

キーワードでQ&A、テーマを検索する
-PR-
-PR-
-PR-

特集


いま みんなが気になるQ&A

-PR-

ピックアップ

-PR-
ページ先頭へ