C言語:構造体、共用体


1. 構造

構造体は、さまざまな要素タイプの要素のコレクションです。

1. 構造体の宣言と構造体変数の定義

構造体の宣言は、タグ名 (tag)、メンバー リスト (member-list)、変数リスト (variable-list) の 3 つの部分で構成されます。
学生タイプを宣言したい場合は、次のようにします。
ここに画像の説明を挿入
変数を定義したい場合は、2 つの方法があります。

  • 構造体型を使用して変数を直接定義する
  • 変数リストで変数を定義する

次のように:

//在变量列表中定义变量s1,s2
struct Student
{
    
    
	char name[20];//名字
	int age;//年龄
	char sex[5];//性别
	char id[20];//学号
}s1; s2;


int main()
{
    
    
	//使用结构体类型定义变量s3
	struct Student s3;

	return 0;
}

さらに、次のように匿名の宣言 (不完全な宣言) を行うこともできます。

//不完全声明
struct
{
    
    
	char c;
	short b;
	int a;
};

この場合、構造体の型がわからないため、変数リスト内でのみ変数を定義したいと考えています。
次のように:

//定义变量s1,s2,s3
struct
{
    
    
	char c;
	short b;
	int a;
}s1; s2; s3;

2 つの同一の構造体を正確に宣言しない場合、コンパイラは 2 つの構造体が異なる型であるとみなします。
次のように:

//定义变量s1,s2,s3
struct
{
    
    
	char c;
	short b;
	int a;
}s1; s2; s3;

//定义指针ps
struct
{
    
    
	char c;
	short b;
	int a;
}*ps;

int main()
{
    
    
	ps = &s1;

	return 0;
}

ここに画像の説明を挿入

2. 構造体変数の初期化

構造体変数を初期化するには 2 つの方法があります。

  1. 変数は変数リストで初期化できます
struct Student
{
    
    
	char name[20];//名字
	int age;//年龄
	char sex[5];//性别
	char id[20];//学号
}s1 = {
    
     "李四", 20, "男", "123456" };
  1. 型で定義されている場合は、変数を初期化します
struct Student
{
    
    
	char name[20];//名字
	int age;//年龄
	char sex[5];//性别
	char id[20];//学号
};

int main()
{
    
    
	struct Student s1 = {
    
     "李四", 20, "男", 123456 };

	return 0;
}

3. 構造体のメンバーにアクセスする

構造体変数がそのメンバーにアクセスするには、. 演算子を使用してアクセスします。
構造体ポインター変数がそれが指すメンバーにアクセスするには、 -> 操作メソッドを使用してアクセスします。
次のように:

struct A
{
    
    
	char a;
	int b;
};

int main()
{
    
    
	struct A a = {
    
     0 };
	struct A* pa = &a;

	a.b = 10;
	printf("%d\n", a.b);

	pa->b = 20;
	printf("%d\n", pa->b);

	return 0;
}

結果は次のとおりです。
ここに画像の説明を挿入

4. 構造体のメモリアラインメント

構造体のメモリ アライメントを導入するには、構造体のサイズを計算する必要があります。
次の構造物のサイズはどれくらいですか?

struct A
{
    
    
	char a;
	int b;
	char c;
};

int main()
{
    
    
	printf("%d\n", sizeof(struct A));
	return 0;
}

答えは 12 です。これは、構造がメモリにアラインされているためです。
12 がどのように計算されるかを知るには、整列された数値に関する関連ルールを習得する必要があります。

  • 最初の構造体メンバーは常にオフセット 0 にあります。
  • 他のメンバー変数は、そのアライメント番号の整数倍のアドレスにアライメントされる必要があります。
  • 構造体の合計サイズは、最大アライメント (メンバー変数のアライメント) の整数倍です。
  • 構造体がネストされている場合、ネストされた構造体は最大アライメントバイト数の整数倍にアライメントされ、構造体の全体のサイズは最大アライメント数の整数倍になります (ネストされた構造体は構造体のメンバーでもあります)。 )

アライメント = コンパイラのデフォルトのアライメントとメンバーのサイズの小さい方。コンパイラにデフォルトのアライメントがない場合、アライメントはメンバー自体のサイズになります。

ここに画像の説明を挿入
これまでのところ、12 を取得する方法はわかっています。しかし、なぜメモリの調整が必要なのでしょうか?

  1. プラットフォームの理由 (移植の理由)
    すべてのハードウェア プラットフォームが任意のアドレスのデータにアクセスできるわけではありません。一部のハードウェア プラットフォームは、特定のアドレスで特定の種類のデータしかフェッチできません。

  2. パフォーマンスの理由
    データ構造 (特にスタック) は、可能な限り自然な境界上に配置する必要があります。
    アライメントされていないメモリ サイズにアクセスするには、プロセッサは 2 回のメモリ アクセスを行う必要がありますが、アライメントされたメモリ アクセスには 1 回のアクセスだけが必要です。

2. ユニオン(コミュニティ)

名前が示すように、共用体は、この型のメンバーが同じメモリ空間を使用することを意味します。
次のように:
メンバーが char a、int b である共用体型 Union A を宣言します。

union A
{
    
    
	char a;
	int b;
};

それで、そのサイズはどれくらいですか?

union A
{
    
    
	char a;
	int b;
};

int main()
{
    
    
	printf("%d\n", sizeof(union A));

	return 0;
}

答えは4ですが、なぜですか?

  1. 共用体のサイズは少なくともその最大のメンバーのサイズである
  2. 共用体のサイズもそのアライメントの整数倍でなければなりません

ここに画像の説明を挿入
上図のように、メンバー a とメンバー b は最初のバイトを共有していますが、メンバー a を使用するときにメンバー b を一緒に使用すると、a = はいくらになりますか?

union A
{
    
    
	char a;
	int b;
};


int main()
{
    
    
	union A un = {
    
     0 };
	un.a = 1;
	un.b = 10;

	printf("%d\n", un.a);

	return 0;
}

答えは a = 10 です。メモリ内の変更だけを確認する必要があります。
ここに画像の説明を挿入


要約する

以上が構造体と共用体に関するここに画像の説明を挿入
知識のまとめです。

おすすめ

転載: blog.csdn.net/li209779/article/details/131889487