0

タイプ「quote」の配列を含む循環バッファの構造体を作成しようとしています。ただし、quote 配列は 10 のサイズで開始する必要があります。.h ファイルまたは .c ファイルでサイズ 10 を宣言するかどうかを調べようとしています。私の2つのファイルは次のとおりです。

.h ファイル:

typedef struct{
    unsigned int time;
    double rate;

}quote;

typedef struct{

    unsigned int testNum;
    quote quoteBuffer[];

}cbuf;

cbuf* cbuf_init();

.c ファイル:

cbuf* cbuf_init(){

    cbuf *buffer = (cbuf *)calloc(1,sizeof(cbuf));
    buffer->testNum = 1;
    quote newQuote = {1,1.00};
    buffer->quoteBuffer[1] = newQuote;
    return buffer;


}

これらは明らかに単なるテスト値ですが、cbuf 構造体の引用配列を 10 のサイズで開始するようにしたい場合は、.h ファイルで次のように宣言します。

typedef struct{

    unsigned int testNum;
    quote quoteBuffer[10];

}cbuf;

または他の方法で.cファイルに?

4

3 に答える 3

2

構造体に動的配列を含める方法は 2 つあります。もちろん、それをポインターとして保持し、必要に応じて動的に割り当てる (または再割り当てする) ことは明らかです。


もう 1 つは、サイズ 1 の配列を持ち、配列に対応するために、構造体よりも大きなサイズを割り当てることです。

typedef struct {
    unsigned int testNum;
    quote quoteBuffer[1];
} cbuf;

cbuf *cbuf_init(const size_t num_quotes) {
    /* Allocate for the `cbuf` structure, plus a number of `quote`
     * structures in the array
     */
    cbuf *buffer = malloc(sizeof(cbuf) + (num_quotes - 1) * sizeof(quote));

    /* Other initialization */

    return buffer;
}

/* If more quotes are needed after initial allocation, use this function */
cbuf *cbuf_realloc(cbuf *buffer, const size_t new_num_quotes) {
    buffer = realloc(buffer, sizeof(cbuf) + (new_num_quotes - 1) * sizeof(quote));

    /* Other initialization */

    return buffer;
}

これで、配列を通常の配列として使用できます。

cbuf *buffer = cbuf_init();
buffer->quoteBuffer[5].time = 123;

注:私は9 つ quoteの構造体に余分なスペースを割り当てるだけですが、10 個を割り当てると述べています。その理由は、構造体の配列にcbuf既に 1 つの構造体が含まれているためです。quote1 + 9 = 10。:)

注 2:下位互換性のために、1 つのエントリが既に含まれている構造体にquote配列を配置しました。cbuf構造体にサイズのない配列を持つことは、C の世界ではまったく新しいことです。

于 2013-04-29T08:40:43.040 に答える
1

cbuf に 10 個の引用符が必要な場合でも、これを行うことができますが、quote buffer[10] のように静的に割り当てられたものも機能します。

cbuf* cbuf_init(int numQuotes)
{
    cbuf *b = calloc(1, sizeof(cbuf) + numQuotes * sizeof(quote));

    return b;
}
于 2013-04-29T08:40:15.513 に答える
1

静的なサイズの循環バッファーが必要な場合は、ヘッダー ファイルでサイズを宣言できます。バッファー サイズに #define を使用すると、コードの他の場所でサイズを参照するため、コードが読みやすく、保守しやすくなります。

循環バッファーを拡張可能にする場合は、C ファイルでサイズを定義します。次に、サイズを追跡し、動的に割り当てる必要があるメモリを破棄する必要があります。

あなたの例では、引用構造体により多くのスペースを割り当てる必要があると思います...

cbuf *buffer = (cbuf *)calloc(1,sizeof(cbuf) + NUM_QUOTES*sizeof(struct quote));
                                             ---------------------------------

この理由は、あなたの構造体定義で...

quote quoteBuffer[];

... quoteBuffer は構造体にサイズを追加しません。quoteBuffer は、構造体の末尾を 1 バイト過ぎたところを指すため、構造体用のメモリ + 配列用のメモリを割り当てる必要があります。

編集: Daniel Fischer のコメント (ダニエルに感謝) - quoteBuffer は、場合によっては、パディングを導入すると構造体にサイズを追加することがあります。その理由は、おそらくコンパイラが quoteBuffer の最適なアラインメントを得ようとするからです。たとえば、int は通常 4 バイト境界にアラインされます。たとえば、次のような構造体:

struct {
   char a;
   int b;
}

おそらくコンパイラによって次のように変更されます

struct {
   char a;
   char pad[3]; // compiler adds padding behind the scenes 
   int b; // align b on a 4-byte boundary
}

構造体が quoteBuffer[] を 4 バイト境界に残すため、この問題はあなたの場合には当てはまりません。

コンパイラがこれを行う理由は 2 つあります。1. 一部のアーキテクチャ (最近ではあまり一般的ではないと思いますか?) では、アライメントされていないアクセスがサポートされていません。2. 2 つのメモリ読み取りと 1 回の操作ではなく 1 回のメモリ読み取りであるため、アーキテクチャが非整列アクセスを許可している場合でも、整列アクセスはより効率的です。

于 2013-04-29T08:46:00.457 に答える