下のような構造体があり、
dataポインタ変数の先頭アドレスがheaderの次にくるようにしたいのですが、
どのように記述すればいいのでしょうか。
struct hoge{
int header ;
unsigned char *data ;
} ;
malloc()を使ってみたのですがポインタ開始位置が勝手に決められてしまうようなので
うまくいきませんでした。
データがこういう風に並んでいてほしいわけですね?
[ header ]
[ data[0] ]
[ data[1] ]
[ data[2] ]
[ data[3] ]
:
ならば、headerを含んだサイズ分を一緒に確保して、その先頭アドレスを
hoge* として扱うのがいいです。
struct hoge {
int header;
unsigned char data[ 1 ];// 変更
};
// 作るとき
int data_size = XXX; // data[]に必要なサイズ
int hoge_size = sizeof( int ) + data_size; // <int header>分のサイズを足す
void* pv = malloc( hoge_size );
hoge* phoge = ( hoge* )pv;
phoge->header = data_size;
// 消すとき
free( phoge );
ただし、hoge hogearray[ 10 ]; という使い方はできなくなりますが。
ありがとうございます。
上記の方法でできました。
いままでmalloc()は割り当てる型をいくつ入れるか程度にしか考えていませんでした。
ある一つのメンバ変数だけ並べることもできるんですね。
実は、プログラムに組み込む際、2重の構造体になっていて、
上の方法でもうまくいかなかったので、
単一の構造体に展開してやりました。
解決はしましたが、
もし2重の構造体の場合はどのようにすればいいのでしょうか。
イメージとしてはこんな感じです。
[header]
[data[0]]---[time[0]]
[data[1]] [time[1]]
[data[2]] .
. .
. .
. [event[0]]
[event[1]]
.
.
.
<アドレスの順番>
[header]->[data[0]]->[time[0]]->[time[1]]->...->
[event[0]]->[event[1]]->...->[data[1]]->[time[0]]->...
構造体は以下の通りです。
struct DATA {
unsigned char time[1] ;
unsigned char event[1] ;
} ;
struct HOGE {
int header ;
struct DATA *data[1] ;
} *hoge ;
結局 *hoge のメンバ変数の *data をmalloc()で割り当てることになってしまうため
うまくいきませんでした。
// 作ってみました。
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
struct TIME {
int count;
unsigned char uc[ 1 ];
// uc[ 1 ] となっているが、実際のサイズはcountで計る
};
struct EVENT {
int count;
unsigned char uc[ 1 ];
// 上に同じ
};
struct DATA {
struct TIME time;
// 理論上EVENTもこの構造体に含めるのだが、正確な位置が不明なので書けない
};
struct HOGE {
int count_of_data;
// count_of_data の後に data[ 0 ] があるということだけが確実
struct DATA data[ 1 ];
};
// DATA内のTIMEの位置を返す
struct TIME* WhereIsTheTime( struct DATA* pData ) {
return &pData->time;
}
// どこにあるかわからないEVENTの位置を実行時に計算する
struct EVENT* WhereIsTheEvent( struct DATA* pData ) {
// time.uc[ time.count-1 ] の直後が次のEVENT
return ( struct EVENT* )( &pData->time.uc[ pData->time.count ] );
}
// さらにどこにあるかわからない次のDATAの位置も実行時に計算する
struct DATA* WhereIsTheNextData( struct DATA* pData ) {
struct EVENT* pEvent = WhereIsTheEvent( pData );
// event.uc[ event.count-1 ] の直後が次のDATA
return ( struct DATA* )( &pEvent->uc[ pEvent->count ] );
}
struct DATA* WhereIsTheData( struct HOGE* pHoge, int iData ) {
// 計算していかないとどこに何番目のDATAがあるのかわからない
struct DATA* pData = pHoge->data;
int i = 0;
while ( i < iData ) {
pData = WhereIsTheNextData( pData );
++i;
}
return pData;
}
// 要素数からのサイズ計算
int CalcSizeOfTime( int count_of_uc ) {
return sizeof( int ) + sizeof( unsigned char ) * count_of_uc;
}
int CalcSizeOfEvent( int count_of_uc ) {
return sizeof( int ) + sizeof( unsigned char ) * count_of_uc;
}
int CalcSizeOfData( int count_of_time_uc, int count_of_event_uc ) {
return CalcSizeOfTime( count_of_time_uc ) + CalcSizeOfEvent(
count_of_event_uc );
}
int CalcSizeOfHoge( int count_of_data, int count_of_time_uc[], int
count_of_event_uc[] ) {
int i = 0;
int whole_size = sizeof( int );
while ( i < count_of_data ) {
whole_size += CalcSizeOfData( count_of_time_uc[ i ], count_of_event_uc[
i ] );
++i;
}
return whole_size;
}
// 続く
// 続き
// 簡便
struct TIME* GetTime( struct HOGE* pHoge, int iData ) {
return WhereIsTheTime( WhereIsTheData( pHoge, iData ) );
}
struct EVENT* GetEvent( struct HOGE* pHoge, int iData ) {
return WhereIsTheEvent( WhereIsTheData( pHoge, iData ) );
}
// malloc() したHOGEの初期化
void InitHoge( struct HOGE* pHoge, int whole_size, int count_of_data, int
count_of_time_uc[], int count_of_event_uc[] ) {
struct TIME* pTime;
struct EVENT* pEvent;
int i = 0;
pHoge->count_of_data = count_of_data;
while ( i < count_of_data ) {
pTime = GetTime( pHoge, i );
pTime->count = count_of_time_uc[ i ];
memset( pTime->uc, 0, count_of_time_uc[ i ] );
pEvent = GetEvent( pHoge, i );
pEvent->count = count_of_event_uc[ i ];
memset( pEvent->uc, 0, count_of_event_uc[ i ] );
++i;
}
}
// 検証
void OutputHoge( struct HOGE* pHoge ) {
struct DATA* pData;
struct TIME* pTime;
struct EVENT* pEvent;
int j = 0;
int i = 0;
printf( HOGE*:[%x] count_of_data:[%d]\n, pHoge, pHoge->count_of_data );
while ( i < pHoge->count_of_data ) {
pData = WhereIsTheData( pHoge, i );
pTime = GetTime( pHoge, i );
pEvent = GetEvent( pHoge, i );
printf( DATA*:[%x]\n, pData );
printf( TIME*:[%x] count:[%d] uc:, pTime, pTime->count );
j = 0;
while ( j < pTime->count ) {
printf( \'%d\',, pTime->uc[ j ] );
++j;
}
printf( \n EVENT*:[%x] count:[%d] uc:, pEvent, pEvent->count );
j = 0;
while ( j < pEvent->count ) {
printf( \'%d\',, pEvent->uc[ j ] );
++j;
}
printf( \n );
++i;
}
}
int main()
{
struct HOGE* pHoge;
// HOGE の領域の確保と初期化
// data[] の数、各々の time.uc[]、event.uc[] のサイズは全て確保前にわかってい
る必要がある
int count_of_data = 2;
int count_of_time_uc[] = { 3, 2 };
int count_of_event_uc[] = { 4, 1 };
int whole_size = CalcSizeOfHoge( count_of_data, count_of_time_uc,
count_of_event_uc );
pHoge = ( struct HOGE* )malloc( whole_size );
InitHoge( pHoge, whole_size, count_of_data, count_of_time_uc,
count_of_event_uc );
OutputHoge( pHoge );
return 0;
}
// 長くてすいません...