web-dev-qa-db-ja.com

Cで配列のみを含む構造体を宣言するのはなぜですか?

私は以下を含むいくつかのコードに遭遇しました:

struct ABC {
    unsigned long array[MAX];
} abc;

このような宣言を使用するのはいつ意味がありますか?

130
Joe.Z

配列を値によって関数に渡すか、関数から値によって返されるようにすることができます。

これらのコンテキストでポインタに減衰する配列とは異なり、構造体は値で渡すことができます。

183

もう1つの利点は、サイズが抽象化されるため、そのようなオブジェクトを宣言する場所ではコード全体で[MAX]を使用する必要がないことです。これは、

typedef char ABC[MAX];

しかし、あなたははるかに大きな問題を抱えています:ABCが配列型であること(ABC型の変数を宣言するときにこれを見ることができない場合でも)またはその他のことを認識する必要がありますABCは、関数の引数リストと変数の宣言/定義では異なる意味を持つという事実に悩まされます。

もう1つの利点は、構造体を使用すると、多くのコードを書き直さなくても、後で必要に応じて要素を追加できることです。

構造体をコピーして、関数から構造体を返すことができます。

配列でそれを行うことはできません-構造体の一部でない限り!

45
Bo Persson

このようにコピーできます。

struct ABC a, b;
........
a = b;

配列の場合は、memcpy関数またはループを使用して各要素を割り当てる必要があります。

26
MetallicPriest

Structを使用して、stringのような新しいタイプのデータを作成できます。あなたが定義することができます:

struct String {
    char Char[MAX];
};

または、関数の引数で使用したり、メソッドで返すことができるListのデータを作成できます。 =のようないくつかの演算子をサポートでき、その中にいくつかのメソッドを定義できるため、構造体は配列よりも柔軟性があります。

それがあなたに役立つことを願っています:)

11

そのようなstructを使用するもう1つの利点は、そのようなstructが使用されている場合は常にタイプセーフを強制するであることです。特に、異なる目的で使用される同じサイズの配列で構成される2つのタイプがある場合、これらのタイプは、誤って配列を不適切に使用することを防ぐのに役立ちます。

配列をstructでラップしない場合でも、typedefを宣言できます。これには、structのいくつかの利点があります–•型が宣言されます•サイズが自動的に正しくなる•コードの目的がより明確になる•コードの保守性が向上する–ただし、厳密な型安全性が失われる◦タイプの値をコピーして返す機能が失われる◦追加できる機能がなくなる残りのコードを壊すことなく後でメンバー。与えられたタイプのベア配列の2つのtypedefsは、サイズが異なる場合にのみ異なるタイプを生成します。さらに、関数の引数で*なしでtypedefを使用すると、char *と同等になり、型の安全性が大幅に低下します。

要約

typedef struct A_s_s { char m[113]; } A_s_t; // Full type safey, assignable
typedef char   A_c_t[113];                   // Partial type-safety, not assignable

A_s_t          v_s(void);     // Allowed
A_c_t          v_c(void);     // Forbidden

void           s__v(A_s_t);     // Type-safe, pass by value
void           sP_v(A_s_t *);   // Type-safe
void           c__v(A_c_t);     // UNSAFE, just means char * (GRRR!)
void           cP_v(A_c_t *);   // SEMI-safe, accepts any array of 113
2
PJTraill

構造には、OOPメモリ管理パラダイムのいくつかの利点をエミュレートする配列初期化、コピー、およびfini関数を含めることができます。実際、この概念を拡張して汎用メモリ管理ユーティリティ( sizeof()構造体を使用して、管理されているバイト数を正確に把握し、ユーザー定義の構造体を管理します。Cで記述されたスマートプロダクションコードベースの多くは、これらを頻繁に使用し、スコープが非常にローカルでない限り、通常は配列を使用しません。

実際、構造に埋め込まれた配列の場合、この配列にアクセスしたいときはいつでも、境界チェックなどの他の「スマートなこと」を実行できます。繰り返しになりますが、配列のスコープが非常に限られている場合を除き、配列のスコープを使用してプログラム間で情報を渡すことはお勧めできません。遅かれ早かれ、夜に目を覚まし、週末を台無しにするバグに遭遇します。

1
Aniket