カスタム型: ビットフィールド、列挙型、共用体

序文

カスタム型の構造を学習したら、さらに 3 つのカスタム型を学習する必要があります.今日は、カスタム型のビット セグメント、列挙型、および共用体を紹介します。

1. ビットセグメント

1.1 ビットセグメントとは

ビット セグメントの宣言は、実際には構造に似ていますが、次の 2 つの違いがあります。

1. ビット セグメントのメンバーは、int、unsigned int、または signed int (整数) でなければなりません。
2. ビットセグメントのメンバ名の後にコロンと数字があります。

例えば

struct A
{
    
    
 int _a:2;
 int _b:5;
 int _c:10;
 int _d:30;
};

ビット セグメントのビットはバイナリ ビットを指し、各ビット セグメント メンバーの後ろの数字は、それが占めるバイナリ ビットの数を示します.
では、ビット セグメント A のサイズは?

printf("%d\n", sizeof(struct A);

ここに画像の説明を挿入
ビット セグメント A のサイズは 8 バイトですが、そのサイズはどのように計算されますか?

ビット セグメント A は最初に 4 バイト スペース (32 バイナリ ビット) を開き、a、b、および c はそれぞれ 2、5、および 10 バイナリ ビットを占有し、残りの 15 バイナリ ビットは d を格納するのに十分ではないため、リセットされます d を格納するために 4 バイトのスペースを開きます

ここに画像の説明を挿入

1.2 ビットセグメントのストレージ割り当て

  1. ビット フィールドのメンバーは、int unsigned int signed int または char (整数ファミリに属する​​) 型にすることができます。
  2. ビットフィールドのスペースは、必要に応じて 4 バイト (int) または 1 バイト (char) の形式で開かれます。
  3. ビット セグメントには多くの不確定要素が含まれ、ビット セグメントはクロスプラットフォームではなく、移植性を重視するプログラムではビット セグメントの使用を避ける必要があります。
//一个例子`在这里插入代码片`
struct S
{
    
    
 char a:3;
 char b:4;
 char c:5;
 char d:4;
};
struct S s = {
    
    0};
s.a = 10;
s.b = 12;
s.c = 3;
s.d = 4;
//空间是如何开辟的?

ここに画像の説明を挿入

1.3 ビット セグメントに関するクロスプラットフォームの問題

  1. int ビット フィールドが符号付きまたは符号なしとして扱われるかどうかは未定義です。
  2. ビット フィールドの最大ビット数を特定できません。(16 ビット マシンでは最大 16、32 ビット マシンでは最大 32、27 と表記されます。16
    ビット マシンでは問題が発生します。
  3. ビット フィールドのメンバーがメモリ内で左から右に割り当てられるか、右から左に割り当てられるかは未定義です。
  4. 構造体に 2 つのビット フィールドが含まれており、2 番目のビット フィールドのメンバーが大きすぎて最初のビット フィールドの残りのビットを収容できない場合、
    残りのビットを破棄するか利用するかは不明です。
    要約:
    構造と比較すると、ビット セグメントは同じ効果を達成できますが、スペースを非常に節約できますが、クロスプラットフォームの問題があります。

1.4 ビットセグメントの適用

ここに画像の説明を挿入

2.列挙

エニュメレーションはその名の通り、一つ一つ列挙することです。
可能な値をすべてリストします。
たとえば、私たちの実生活では:

月曜日から日曜日までの 1 週間に 7 日しかないため、1 つずつリストアップできます。
性別:男性、女性、内密、1つずつ記載も可能です。
月は 12 か月あり、1 か月ずつ一覧表示することもできます。

ここでは列挙型を使用できます。

2.1 列挙の定義

enum Day//星期
{
    
    
 Mon,
 Tues,
 Wed,
 Thur,
 Fri,
 Sat,
 Sun
};
enum Sex//性别
{
    
    
 MALE,
 FEMALE,
 SECRET
}enum Color//颜色
{
    
    
 RED,
 GREEN,
 BLUE
};

上で定義した enum Day、enum Sex、enum Color はすべて列挙型です。
{} の内容は、列挙定数とも呼ばれる列挙型の可能な値です。
これらの可能な値はすべて有効で、デフォルトでは 0 から始まり、一度に 1 ずつ増加します. もちろん、定義時に初期値を割り当てることもできます.
ここに画像の説明を挿入

例えば:

enum Color//颜色
{
    
    
 RED,
 GREEN,
 BLUE=4,
 BLACK
};

ここに画像の説明を挿入

2.2 列挙の利点

#define を使用して定数を定義できますが、なぜ列挙型を使用するのでしょうか?
列挙型の利点:

  1. コードの可読性と保守性を向上
  2. #define で定義された識別子と比較すると、列挙型にはより厳密な型チェックがあります。
  3. ネーミング汚染の防止 (カプセル化)
  4. デバッグが容易
  5. 使いやすく、一度に複数の定数を定義できます

switch 文を使うときは列挙変数を使うことができます. 例えばゲームをデザインするとき, case exit (0) を exit, case play (1) をゲームのプレイとみなすことができます.
ここに画像の説明を挿入

3. コンソーシアム(コミュニティ)

4.1 共用体型の定義

共用体も特殊なカスタム型で、
この型で定義される変数にも一連のメンバーが含まれており、これらのメンバーが同じ空間を共有しているのが特徴です (したがって、共用体は共用体とも呼ばれます)。
例えば:

//联合类型的声明
union Un
{
    
    
 char c;
 int i;
};
//联合变量的定义
union Un un;
//计算连个变量的大小
printf("%d\n", sizeof(un));

ここに画像の説明を挿入

3.2 コンソーシアムの特徴

共用体のメンバーは同じメモリ空間を共有し、そのようなジョイント変数のサイズは少なくとも最大のメンバーのサイズです (共用体は少なくとも最大のメンバーを保存する機能を持っている必要があるため)

union Un
{
    
    
 int i;
 char c;
};
union Un un;
// 下面输出的结果是一样的吗?
printf("%d\n", &(un.i));
printf("%d\n", &(un.c));
//下面输出的结果是什么?
un.i = 0x11223344;
un.c = 0x55;
printf("%x\n", un.i);

ここに画像の説明を挿入
ここで、i と c のアドレスが同じであり、同じ空間を占めていることがわかります。

4.3 ジョイントサイズの計算

1. 共用体のサイズは、少なくとも最大のメンバーのサイズです。
2. 最大メンバ サイズが最大アラインメント数の整数倍でない場合は、最大アラインメント数の整数倍にアラインメントする必要があります。
例えば:

union Un1
{
    
    
 char c[5];
 int i;
};
union Un2
{
    
    
 short c[7];
 int i;
};
//下面输出的结果是什么?
printf("%d\n", sizeof(union Un1));
printf("%d\n", sizeof(union Un2));

ここに画像の説明を挿入
ここに画像の説明を挿入
図のようにiとcで最初の5バイトを占めますが、unionのサイズは最大アラインメント数intの整数倍ではないので、8バイト目にアラインする必要があるので、un1のサイズは8 バイト。Un2も同じです。

終わり

さて、これが今日あなたと共有するものです。あなたが何かを得られることを願っています。
来て!

おすすめ

転載: blog.csdn.net/qq_65673848/article/details/129768271
おすすめ