メモリ確保(再)

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Cユーザー

メモリ確保(再)

#1

投稿記事 by Cユーザー » 7年前

こんばんわ、C言語の勉強を始めたものです。
以下の構造体でメモリ確保を行うには
SAMPLE *sample = (SAMPLE *) malloc(sizeof(SAMPLE));
と確保できるのはわかりました。
しかし例えば

SAMPLE *sample = (SAMPLE *) malloc(500);
と余分にメモリを確保した場合、メモリ的にどういう構造になるのでしょうか?

handle→4バイト
number→4バイト
str→4バイト

[handle(4バイト)] + [number(4バイト)] + [str(4バイト)] + [余分なゴミメモリ(488バイト)]

①こんな構造のメモリ領域ができあがると考えていますが、正しいでしょうか?

SAMPLE *sample = (SAMPLE *) malloc(500)とした後
sample->str = (char*)malloc(600);

とした場合、
②この場合、構造体メンバーの確保領域が、構造体の確保領域を超えているのですが、これはどういう状態になりますか?
エラーにはなりませんでした。

SAMPLE *sample = (SAMPLE *) malloc(500)とした後
sample->str = (char*)malloc(300);

とした場合、
③構造体のメモリ領域は以下のようになると考えています。正しいでしょうか?

[handle(4バイト)] + [number(4バイト)] + [str(300バイト)] + [余分なゴミメモリ(192バイト)]


①~③が質問です。
以上、よろしくお願いいたします。

コード:

struct SAMPLE
{
    HANDLE handle;
    int number;
    char *str;
}; 

アバター
h2so5
副管理人
記事: 2212
登録日時: 9年前
住所: 東京
連絡を取る:

Re: メモリ確保(再)

#2

投稿記事 by h2so5 » 7年前

Cユーザー さんが書きました: SAMPLE *sample = (SAMPLE *) malloc(500);
と余分にメモリを確保した場合、メモリ的にどういう構造になるのでしょうか?

handle→4バイト
number→4バイト
str→4バイト

[handle(4バイト)] + [number(4バイト)] + [str(4バイト)] + [余分なゴミメモリ(488バイト)]

①こんな構造のメモリ領域ができあがると考えていますが、正しいでしょうか?
メモリアドレスが32bitの場合はそのようになります。
Cユーザー さんが書きました: SAMPLE *sample = (SAMPLE *) malloc(500)とした後
sample->str = (char*)malloc(600);

とした場合、
②この場合、構造体メンバーの確保領域が、構造体の確保領域を超えているのですが、これはどういう状態になりますか?
エラーにはなりませんでした。
構造体メンバーの確保領域は、構造体の確保領域を超えていません。
この場合もsampleは4byteです。
Cユーザー さんが書きました: SAMPLE *sample = (SAMPLE *) malloc(500)とした後
sample->str = (char*)malloc(300);

とした場合、
③構造体のメモリ領域は以下のようになると考えています。正しいでしょうか?

[handle(4バイト)] + [number(4バイト)] + [str(300バイト)] + [余分なゴミメモリ(192バイト)]
違います。

[handle(4バイト)] + [number(4バイト)] + [str(4バイト)] + [余分なゴミメモリ(488バイト)]

[(300バイト)]
の2つの領域が確保されます。この領域は連続しているとは限りません。
そして、strへ300byteの領域の先頭のアドレスが代入されます。

Cユーザー

Re: メモリ確保(再)

#3

投稿記事 by Cユーザー » 7年前

ご返信ありがとうごさます。

なるほど、そういう仕組みなんですね。

もう1点質問させてください。逆に、
handle(4バイト)] + [number(4バイト)] + [str(300バイト)] + [余分なゴミメモリ(192バイト)]

となるような、確保領域の再設定?は可能でしょうか?
可能であれば方法をご教授いただきたいです。

アバター
h2so5
副管理人
記事: 2212
登録日時: 9年前
住所: 東京
連絡を取る:

Re: メモリ確保(再)

#4

投稿記事 by h2so5 » 7年前

300byte連続してほしいなら

コード:

struct SAMPLE
{
    HANDLE handle;
    int number;
    char str[300];
};
でどうでしょうか?

Cユーザー

Re: メモリ確保(再)

#5

投稿記事 by Cユーザー » 7年前

返信ありがとうございます。

その方法は1つの手ではあるのですが
後から構造体メンバの文字列のメモリを確保したいんです。

コード:

struct SAMPLE
{
    HANDLE handle;
    int number;
    char str[300];
};
だとあらかじめ決まった分しか確保できません。
其のため

コード:

struct SAMPLE
{
    HANDLE handle;
    int number;
    char *str;
};
としておいて、後からメモリを確保したいんですよね。
それでhandle(4バイト) + number(4バイト) + str(300バイト)

というような無駄なメモリもなくメモリを使いたい。実はこれが一番やりたいことです。

何か方法はないでしょうか
以上、よろしくお願いいたします。

アバター
h2so5
副管理人
記事: 2212
登録日時: 9年前
住所: 東京
連絡を取る:

Re: メモリ確保(再)

#6

投稿記事 by h2so5 » 7年前

文字列のサイズを可変にしたいだけなら領域が連続している必要もないので、普通に

コード:

SAMPLE *sample = (SAMPLE *) malloc(sizeof(SAMPLE));
sample->str = (char*)malloc(300);
で良いと思います。

Cユーザー(携帯)

Re: メモリ確保(再)

#7

投稿記事 by Cユーザー(携帯) » 7年前

ご返信ありがとうございます。

また疑問が1つできました。

前のレスで300の領域の先頭アドレスが代入されるとありました。
その場合、構造体のメモリ確保時のstrのメモリは無駄メモリになる感じでしょうか?

box
記事: 1746
登録日時: 9年前

Re: メモリ確保(再)

#8

投稿記事 by box » 7年前

Cユーザー さんが書きました: その場合、構造体のメモリ確保時のstrのメモリは無駄メモリになる感じでしょうか?
300バイト確保した分がどこにあるか、というアドレス値を保持するために必須です。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

Cユーザー(携帯)

Re: メモリ確保(再)

#9

投稿記事 by Cユーザー(携帯) » 7年前

なるほど。

ご教授ありがとうございました

Cユーザー(携帯)

Re: メモリ確保(再)

#10

投稿記事 by Cユーザー(携帯) » 7年前

すいません

解決チェック押し忘れです

ISLe
記事: 2646
登録日時: 9年前
連絡を取る:

Re: メモリ確保(再)

#11

投稿記事 by ISLe » 7年前

Cユーザー さんが書きました:というような無駄なメモリもなくメモリを使いたい。実はこれが一番やりたいことです。
構造体の最後のメンバを要素数1の配列にします。
#処理系によっては要素数0が使えます。

コード:

struct SAMPLE
{
	HANDLE handle;
	int number;
	char str[1];
};
必要な配列の要素数分を余分にメモリ確保します。

コード:

struct SAMPLE *sample = (struct SAMPLE *)malloc(sizeof(struct SAMPLE)+300-1);
こうするとsample->strは要素数が300あるかのように使えます。

YuO
記事: 941
登録日時: 9年前
住所: 東京都世田谷区

Re: メモリ確保(再)

#12

投稿記事 by YuO » 7年前

ISLe さんが書きました:構造体の最後のメンバを要素数1の配列にします。
#処理系によっては要素数0が使えます。
標準C的には,要素数を記述しない,ですね。
# ISO/IEC 9899:1999 6.7.2.1 Structure and union specifiers ¶16
ISLe さんが書きました:

コード:

struct SAMPLE
{
	HANDLE handle;
	int number;
	char str[1];
};
標準Cが使えるならば,

コード:

struct SAMPLE
{
	HANDLE handle;
	int number;
	char str[];
};
とするとよいでしょう。
この場合,1を引く作業は不要です。
ただ,標準Cではあるものの標準C++ではない (標準C++の標準CとのCompatibility欄にすら書いていない) のが問題点ですが。
# 配列まわりはCとC++で非互換が……。

アバター
へにっくす
記事: 630
登録日時: 8年前
住所: 東京都

Re: メモリ確保(再)

#13

投稿記事 by へにっくす » 7年前

ISLe さんが書きました:
Cユーザー さんが書きました:というような無駄なメモリもなくメモリを使いたい。実はこれが一番やりたいことです。
構造体の最後のメンバを要素数1の配列にします。
#処理系によっては要素数0が使えます。

コード:

struct SAMPLE
{
	HANDLE handle;
	int number;
	char str[1];
};
必要な配列の要素数分を余分にメモリ確保します。

コード:

struct SAMPLE *sample = (struct SAMPLE *)malloc(sizeof(struct SAMPLE)+300-1);
こうするとsample->strは要素数が300あるかのように使えます。
これってWin32APIの構造体でよく見かけますね。
SDKのIncludeヘッダで、"[1]"で検索すると結構ヒットする。
これを使用する場合、たいていはどれだけの長さがあるかも構造体のメンバに入れてます。
例:winnt.hの一部

コード:

typedef struct _JOBOBJECT_BASIC_PROCESS_ID_LIST {
    DWORD NumberOfAssignedProcesses;
    DWORD NumberOfProcessIdsInList;
    ULONG_PTR ProcessIdList[1];
} JOBOBJECT_BASIC_PROCESS_ID_LIST, *PJOBOBJECT_BASIC_PROCESS_ID_LIST;

typedef struct _FILE_NOTIFY_INFORMATION {
    DWORD NextEntryOffset;
    DWORD Action;
    DWORD FileNameLength;
    WCHAR FileName[1];
} FILE_NOTIFY_INFORMATION, *PFILE_NOTIFY_INFORMATION;
まあWindows SDKでは常套手段ってことで参考になれば。
スレ汚しすみません。
written by へにっくす

閉鎖

“C言語何でも質問掲示板” へ戻る