
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] 以降の領域は確保されていないから
後で、知らないうちに値が変わっている可能性がある。
という想像をしてみたけど、あってますか?
No.1ベストアンサー
- 回答日時:
こんにちは、honiyonです。
ハズレです。
最初に 4byte確保したなら、str[2] = NULL; としても 4byte確保されています。
char*型はあくまで「char型へのポインタ」であり、メモリの操作は行いません。
0x00 も立派な「データ」ですよ。
char* = 文字列データ という意味合いが強いですが、あくまで char型は「0~255の整数型」であり、それ以外の用途にも使用される事があります。 char* でメモリを確保し、バイナリデータを扱う事だって出来ます。
参考になれば幸いです(..
ありがとうございます。
ハズレでしたか。
メモリの操作は行わないという意味が分かりませんでした。
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;
で宣言したポインタに大きなサイズのデータを格納した場合、
プログラムが終了するまで、その大きなサイズを確保しているのは
よくないことだから解放したいと思って質問しました。
No.7
- 回答日時:
> char *str[] = {0x61, 0x0, 0x64};
失礼しました。私のタイプミスです(笑)
ご指摘ありがとうございました。
*はいらないですね。
> char str[] = {0x61, 0x0, 0x64};
回答はみなさんの答えで的を得ています。
質問者がの処理系が違っていた場合には記述の曖昧さで悩んでしまうと可哀想かなと思ったので補足をしてみました。余計でしたら申し訳ないです。
そういう自分が上記のようなタイプミスしているくらいですから、私自身もまだまだ甘いですね。ただのタイプミスといえど挙動はかなり違いますからね。
No.6
- 回答日時:
No.5 の方が「処理系依存」のことについて触れられていますが、それについてちょっとアドバイスを。
>signed か unsigned は処理系次第ではなかったでしたっけ。
>4バイトというのと、スタックに確保されるというのも、処理系次第ですよね。
最適化するとレジスタを使ってしまったりする事も。
どちらも確かにその通りです。
でも A__ さんに理解して欲しいのは、
>char * 型は、文字列処理以外にも使用される、ということ
>ポインタ変数と文字列アドレスの関係について
という部分です。
(それを説明するには、どちらも十分な説明だったと思いますが。)
また、私はこの質問を、ポインタ変数を文字列で初期化した場合の、メモリとの関係について尋ねられているものだと思いました。
だとすれば、
> char *str[] = {0x61, 0x0, 0x64};
これでは文字列は生成されませんので、注意が必要です。
この記述では、それぞれのデータをアドレスとするポインタの配列ができるだけです。もちろん操作すると大変危険です。
No.5
- 回答日時:
最近 C 言語をやっていないので懐かしいです。
char *str[] = {0x61, 0x0, 0x64};
なんていう宣言もありですね。
みなさんの回答でちょっと気になった点を。
(あくまで char型は「0~255の整数型」)
signed か unsigned は処理系次第ではなかったでしたっけ。
(関数内で宣言された char * 型の str は、スタックメモリ上に確保されます。無論、確保されるサイズは4バイトです。)
4バイトというのと、スタックに確保されるというのも、処理系次第ですよね。
最適化するとレジスタを使ってしまったりする事も。
なんんだかややこしい話ですね・・・
No.4
- 回答日時:
おもしろい発想です。
C言語勉強し始めの頃は、こんな疑問に大いにぶつかってください。
今回は、皆様の言うとおり、はずれですが。
おまけ情報です。
char*はCスタイルの文字列と呼ばれますが、これは\0(0x00)までを文字範囲とする、という規定の基に、様々な操作がなされます。
確保した領域の中に\0が見つからなければ、文字列操作関数は、確保してある領域を超え、一般保護違反というエラーが発生する危険性を秘めます。
VBやJAVA、Perlの文字列は、\0で終わるという保証はなく、わざわざこの文字列は何文字あるという情報と一緒に、変数を管理します。
でも、これによって\0を途中に含む文字列が作れますし、確保した範囲を超えてアクセスする危険性も低くなります。
ポインタマニアの、はぽるんでした。
No.3
- 回答日時:
# 何か、メモリとポインタ変数との間に、変な誤解を持たれているようですが・・・
「文字列」というのは、確保されるものではありません。例えば、
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
- 回答日時:
> このポインタ str は解放する必要がない。
むしろ、解放したらまずいです。
たぶん。判断されたのは
printfで表示しても
abしか出なかったからだと思いますが、これは\0(0x00)がCに置ける文字列の終わりを示すコードになっているからです。
もし、確保されていなければ、str[3]のアクセス時に不正終了しかねません。「確保されていないメモリ」にアクセスするわけですから。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# str[j++]の意味 2 2022/08/30 16:20
- C言語・C++・C# sprintf()の使い方について 1 2022/08/17 16:16
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# C言語 少しの疑問 4 2022/11/08 02:48
- C言語・C++・C# C# 浮動小数の数値文字列化 1 2022/04/18 15:15
- Visual Basic(VBA) VBA ユーザーフォームからSubプロージャ―に値を引き渡す方法 3 2023/04/09 01:54
- その他(プログラミング・Web制作) python質問 1 2023/08/14 11:54
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ヒープメモリの解放について
-
allocってなんですか?
-
reallocについて
-
C言語で作ったゲームがフリーズ...
-
newしないオブジェクトについて
-
c言語のポインタへの文字列入力...
-
C++のnewで確保したメモリーの...
-
なぜ動かないのかわからないです。
-
C++で、メンバもヒープに確保さ...
-
指定したメモリアドレスの値の...
-
malloc でのメモリ取得状況の可...
-
構造体でchar name[]と*nameの...
-
sprintf()の使い方について
-
C言語 配列の長さの上限
-
関数から配列を返すには?
-
VBAのプログラムで、DIAG = 1# ...
-
引数で指定された配列の要素数...
-
配列の要素数に変数を入れたい...
-
VB.NETでファイル名順にファイ...
-
CStringからchar*への型変換に...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
c言語のポインタへの文字列入力...
-
allocってなんですか?
-
newしないオブジェクトについて
-
malloc呼び出し時のセグメンテ...
-
入れ子になった構造体について
-
ヒープメモリの解放について
-
ビットをローテートするプログ...
-
C++で、メンバもヒープに確保さ...
-
void*型のデータサイズ
-
Win32APIでのメモリ管理について
-
配列の添え字の最大数とは?
-
C++のnewで確保したメモリーの...
-
プログラムが途中で強制終了し...
-
C言語 mallocとfreeについて
-
win32APIのHeapAlloc()の使い方...
-
LoadLibraryでAccess Violation...
-
グローバル変数のサイズ
-
MFCのCStringについて
-
メモリ不足になってしまう。
-
ヒープの実際の限界値は?
おすすめ情報