3

わかりました、これを正しく説明できれば幸いです。私は構造体を持っています:

typedef struct _MyData
{
   char Data[256];
   int  Index;
} MyData;

今、私は問題に遭遇しました。ほとんどの場合、MyData.Data は 256 で問題ありませんが、保持できる文字数をさまざまなサイズに拡張する必要がある場合があります。ポインタが使えません。実行時にデータのサイズを変更する方法はありますか? どのように?コードは大歓迎です。

ありがとう

編集:

私はすべてのコメントに非常に感謝していますが、「多分これを試してみてください...」または「あれをしてください」、または「あなたのドンは間違っています...」コメントは役に立ちません. コードはここで役立ちます。答えがわかっている場合は、コードを投稿してください。

と:

1- ポインターを使用できません。理由を理解しようとしないでください。私にはできません 2-構造体が別のプログラムのメモリに挿入されています。それが理由です。ポインターはありません。

ここで少し大雑把で申し訳ありませんが、うまくいくと思われるさまざまなアプローチをすべて試したので、ここで質問しました。繰り返しますが、私はコードを探しています。現時点では、「うまくいくかもしれない...」や「これを検討したことがありますか...」には興味がありません。

ありがとう、そしてもう一度お詫びします

編集2

なぜこれが回答済みとして設定されたのですか?

4

11 に答える 11

18

柔軟な配列メンバーを使用できます

typedef struct _MyData
{
   int  Index;
   char Data[];
} MyData;

適切な量​​のスペースを割り当てることができるように

MyData *d = malloc(sizeof *d + sizeof(char[100]));
d->Data[0..99] = ...;

後で、メモリの別のチャンクを解放して割り当て、それを指すポインターを作成できMyDataます。その時点で、柔軟な配列メンバーの要素が増減します ( realloc)。長さもどこかに保存する必要があることに注意してください。

C99 より前の時代には、柔軟な配列メンバーはありません。char Data[]単純に不完全な型の配列と見なされ、コンパイラはそれについてうめき声を上げていました。ここで、2つの可能な方法をお勧めします

  • ポインタの使用:char *Data割り当てられたメモリを指すようにします。これは、組み込み配列を使用するほど便利ではありません。おそらく 2 つの割り当てが必要になるからです。1 つは構造体用、もう 1 つはポインターが指すメモリ用です。プログラムの状況で許可されている場合は、代わりに構造体をスタックに割り当てることもできます。
  • 代わりにa を使用しchar Data[1]ますが、割り当てられたオブジェクト全体をオーバーレイするように、より大きなものとして扱います。これは正式には未定義の動作ですが、一般的な手法であるため、おそらくコンパイラで安全に使用できます。
于 2009-07-20T13:42:09.763 に答える
13

ここでの問題は、「ポインタを使用できません」というステートメントです。あなたはそうしなければならないでしょう、そしてそれはすべてをはるかに簡単にするでしょう。ねえ、reallocは既存のデータをコピーすることさえできますが、もっと何が欲しいですか?

では、なぜポインタを使用できないと思いますか?それを修正してみてください。

于 2009-07-20T13:33:34.903 に答える
5

あなたはそのような構造を再配置するでしょう

typedef struct _MyData
{
   int  Index;
   char Data[256];
} MyData;

そして、次のようにmalloc/reallocでインスタンスを割り当てます。

my_data = (MyData*) malloc ( sizeof(MyData) + extra_space_needed );

これは醜いアプローチであり、私はそれをお勧めしません(私はポインターを使用します)が、ポインターなしでそれを行う方法についてのあなたの質問への答えです。

制限は、構造体ごとに1つの可変サイズのメンバーのみを許可し、最後に存在する必要があることです。

于 2009-07-20T13:37:20.467 に答える
5

このスレッドで私が見ている2つの重要なポイントを要約しましょう:

  1. この構造は、IPCメカニズムを介して2つのプログラム間で対話するために使用されます
  2. 宛先プログラムは変更できません

したがって、宛先プログラムが現在定義されているとおりに構造を読み取ろうとしてスタックしているため、その構造を変更することはできません。あなたが立ち往生しているのではないかと思います。

同等の動作を実現する方法を見つけたり、宛先プログラムに新しい構造を強制的に読み取らせるための邪悪なハックを見つけたりすることができます(たとえば、実行可能ファイルのバイナリオフセットを変更する)。それはすべてかなりアプリケーション固有なので、それよりもはるかに優れたガイダンスを提供することはできません。

2つの間のインターフェイスとして機能する3番目のプログラムを作成することを検討してください。「長い」メッセージを受け取り、それらを使って何かを実行し、「短い」メッセージを古いプログラムに渡すことができます。これは、IPCメカニズムの間にかなり簡単に挿入できます。

于 2009-07-29T22:34:15.707 に答える
2

問題はあなたが質問をする方法にあります。Cのセマンティクスについては考えないでください。代わりに、ハッカーのように考えてください。現在、適切なタイミングで他のプロセスにデータを取り込む方法と他のプログラムがデータの開始位置と終了位置をどのように認識しているかを正確に説明します。他のプログラムはnullで終了する文字列を期待していますか?構造体をchar[300]で宣言すると、他のプログラムはクラッシュしますか?

他のプログラムに「データを渡す」と言うと、[a]他のプロセスをだまして、前に置いたものをコピーさせ、[b]他のプログラムをだまして、通常のプライベートを上書きさせる可能性があります。 'メモリ、または[c]他のアプローチ。どちらの場合でも、他のプログラムがより大きなデータを取得できる場合、それらにデータを取得する方法があります。

于 2009-07-29T22:17:02.283 に答える
2

あなたが言っていることから、あなたは間違いなくMyDataデータの静的なブロックとして保持しなければならないように見えます。その場合、あなたに開かれた唯一のオプションは、他のプロセスで再構築できる方法で、これらのデータ構造を何らかの方法で(オプションで)チェーン化することだと思います。

たとえば、に追加のメンバーが必要ですMyData

typedef struct _MyData
{
   int  Sequence;
   char Data[256];
   int  Index;
} MyData;

WhereSequenceは、データを再構成する降順のシーケンスを識別します(シーケンス番号がゼロの場合は、最終的なデータバッファーを示します)。

于 2009-07-28T22:24:34.563 に答える
2

配列にポインターを割り当てずに、次のようにできる場合があります。

typedef struct _MyData
{
    int Index;
    char Data[1];
} MyData;

後で、次のように割り当てます。

int bcount = 256;
MyData *foo;

foo = (MyData *)malloc(sizeof(*foo) + bcount);

再割り当て:

int newbcount = 512;
MyData *resized_foo;

resized_foo = realloc((void *)foo, sizeof(*foo) + newbcount);
于 2009-07-20T13:38:10.500 に答える
0

手動で再調整することはできません。

私が単純なデータ保持システムに取り組んでいたときに私が知っていたいくつかのトリックを行うことができます。(非常に単純なファイルシステム)。

typedef struct
{
    int index ;     
    char x[250];
} data_ztorage_250_char;

typedef struct
{
    int index;      
    char x[1000];
} data_ztorage_1000_char;

int main(void)
{
      char just_raw_data[sizeof(data_ztorage_1000_char)];
      data_ztorage_1000_char* big_struct;
      data_ztorage_250_char* small_struct;
      big_struct = (data_ztorage_1000_char*)big_struct; //now you have bigg struct
      // notice that upper line is same as writing 
      // big_struct = (data_ztorage_1000_char*)(&just_raw_data[0]);

      small_struct = (data_ztorage_250_char*)just_raw_data;//now you have small struct

      //both structs starts at same locations and they share same memory
     //addresing data is 
      small_struct -> index = 250;
}
于 2009-07-23T20:41:43.173 に答える
0

Index 値の目的を述べていません。

私が理解しているように、示されている構造を使用して別のプログラムにデータを渡しています。データを分割して 256 バイトのチャンクに送信し、それに応じてインデックス値を設定できない理由はありますか? 例えば

データは 512 バイトであるため、最初の 256 バイトで index=0 の 1 つの構造体を送信し、次に配列内の次の 256 バイトで Index=1 の別の構造体を送信します。

于 2009-07-30T07:41:52.100 に答える
0

KIVのトリックはかなり使えると思います。ただし、最初にポインターの問題を調査することをお勧めします。

malloc の実装を見ると
( IBM の記事 Listing 5: Pseudo-code for the main allocator を参照してください)、
割り当て時に、メモリ マネージャーは制御ヘッダーを割り当て、
要求されたサイズに基づいてそれに続く領域を解放します。
これは、次のように言っているのとよく似ています。

typedef struct _MyData
{
   int  size;
   char Data[1]; // we are going to break the array-bound up-to size length
} MyData;

さて、あなたの問題は、
そのような(サイズが間違っている?)構造をこの他のプロセスにどのように渡すのですか?


これにより、他のプロセスはこのデータのサイズをどのように把握するのかという疑問が生じます。コミュニケーションの一部としてフィールドを
期待します。length

それがすべてある場合、ポインターを他のプロセスに渡すことの何が問題なのですか?
他のプロセスは、構造体へのポインターと割り当てられたメモリへのポインターの違いを識別しますか?

于 2009-07-20T13:46:37.980 に答える
0

本当に簡単な解決策はどうですか?あなたはできますか:

typedef struct _MyData
{
   char Data[1024];
   int  Index;
} MyData;

私はあなたの応答が「いいえ、私が制御できない他のプログラムは256バイトを期待しているため」になることを知っていると感じています...そして、それが私の答えに対するあなたの答えである場合、私の答えは次のようになります:これは不可能です.

于 2009-07-30T18:31:16.337 に答える