web-dev-qa-db-ja.com

memsetを使用した構造体配列の初期化

gcc 4.4.4 c89

次のような構造になっています。

struct device_sys
{
    char device[STRING_SIZE];
    int id;
    char category;
};

int main(void)
{
    struct device_sys dev_sys[NUM_DEVICES];

    memset(dev_sys, 0, (size_t)NUM_DEVICES * sizeof(dev_sys));

    return 0; 
}

Memsetを呼び出すと、スタックダンプが表示されます。これは、構造体配列を初期化する正しい方法ではありませんか?

18
ant2009

どちらか

_memset(&dev_sys, 0, sizeof dev_sys);
_

または

_memset(dev_sys, 0, NUM_DEVICES * sizeof(struct device_sys));
_

または、必要に応じて

_memset(dev_sys, 0, NUM_DEVICES * sizeof *dev_sys);
_

ただし、元のバリアントにはありません。

すべてのバリアントの特定のケースでは、最初の引数として_&dev_sys_または_dev_sys_を使用できることに注意してください。効果は同じです。ただし、memset(ptr-to-object, object-size)イディオムの後に続く場合は、_&dev_sys_が最初のバリアントでより適切です。 2番目と3番目のバリアントでは、memset(ptr-to-first-element, number-of-elements * element-size)イディオムに従うため、_dev_sys_(または_&dev_sys[0]_)を使用する方が適切です。

P.S。もちろん、ハックされたmemsetトリックすべてを使用する代わりに、特定のケースでは、初期化子を使用して配列を宣言するだけで済みます

_struct device_sys dev_sys[NUM_DEVICES] = { 0 };
_

memsetは必要ありません。

34
AnT

コードにタイプミスがあります。修正:

memset(dev_sys, 0, (size_t)NUM_DEVICES * sizeof(struct device_sys));

適切な名前を選択すると、バグの半分が回避されます。 「デバイス」をお勧めします。

9
Hans Passant

配列の場合、sizeofは、個々の要素のサイズではなく、配列全体のサイズを取得します。 sizeof演算子は、配列が最初の要素へのポインターとして扱われない数少ない場所の1つです。

1
Thom Smith

sizeof演算子には、変数ではなくタイプを渡す必要があります。

memset(dev_sys, 0, (size_t)NUM_DEVICES * sizeof(struct device_sys));

構造体にはtypedefを使用します。

typedef struct tag_device_sys
{
    char device[STRING_SIZE];
    int id;
    char category;
} device_sys;

次のようにmemsetを使用できます。

    memset(dev_sys, 0, (size_t)NUM_DEVICES * sizeof(device_sys));
1
Lucas