文章目錄
- 一.位段
- (1).位段介紹
- (2).位段記憶體分配及空間開辟
- (3).位段的可移植性問題
- (4).位段相關練習題
- 二.列舉
- 三.聯合體
- (1).聯合體介紹
- (2).聯合體的計算
一.位段
(1).位段介紹
位段的宣告和結構類似,但它的成員是一個或多個位的欄位,這些不同長度的欄位實際上存盤在一個或多個整形(字符)變數中,
位段的宣告和任何普通的結構成員宣告相同,但有兩個例外
(1). 位段的成員必須是 int、unsigned int 或signed int 或 char 或 unsigned char型別
(2). 位段的成員名后邊有一個冒號和一個整數,這個整數指定該位段所占用位的數目.
// 一個例子
struct A
{
unsigned int a:2;
unsigned int b:5;
unsigned int c:10;
unsigned int d:30;
};
(2).位段記憶體分配及空間開辟
#include<stdio.h>
int main()
{
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;
printf("%d\n", s);
printf("%d\n", sizeof(s));
}
位段的空間上是按照需要以4個位元組( int )或者1個位元組( char )的方式來開辟的
在vs2019的環境下 :
(1).記憶體分配時是從右向左進行分配的,
(2).當下一個位段無法容納于上一個位段的剩余的位時,會再開辟一個空間

(3).位段的可移植性問題
(1). int 位段被當成有符號數還是無符號數是不確定的,
(2). 位段中最大位的數目不能確定,(16位機器整形變數16位,32位機器32位,寫成27,在16位機器會出問題)
(3). 位段中的成員在記憶體中從左向右分配,還是從右向左分配標準尚未定義,
(4).當一個結構包含兩個位段,第二個位段成員比較大,無法容納于第一個位段剩余的位時,是舍棄剩余的位 還是利用,這是不確定的,
總結: 跟結構相比,位段可以達到同樣的效果,但是可以很好的節省空間,但是有跨平臺的問題存在,
(4).位段相關練習題
(1).
#define MAX_SIZE A+B
struct _Record_Struct
{
unsigned char Env_Alarm_ID : 4;
unsigned char Para1 : 2;
unsigned char state;
unsigned char avail : 1;
}*Env_Alarm_Record;
struct _Record_Struct *pointer = (struct _Record_Struct*)malloc
(sizeof(struct _Record_Struct) * MAX_SIZE);
// 當A=2, B=3時,pointer分配( )個位元組的空間,
首先開辟一個位元組的空間,給 Env_Alarm_ID分配4位,Para1分配2位,剩下2位不足以容納 state,再開辟一個位元組空間,再開辟一個空間,分配給 avail 1位
因此 sizeof(struct _Record_Struct)的值為 3 ,結果為 3 * 2 + 3 為 9
(2).
#include<stdio.h>
int main()
{
unsigned char puc[4];
struct tagPIM
{
unsigned char ucPim1;
unsigned char ucData0 : 1;
unsigned char ucData1 : 2;
unsigned char ucData2 : 3;
}*pstPimData;
pstPimData = (struct tagPIM*)puc;
memset(puc,0,4);
pstPimData->ucPim1 = 2;
pstPimData->ucData0 = 3;
pstPimData->ucData1 = 4;
pstPimData->ucData2 = 5;
printf("%02x %02x %02x %02x\n",puc[0], puc[1], puc[2], puc[3]);
return 0;
}

列印結果為 02 29 00 00
二.列舉
列舉顧名思義就是一一列舉,把可能的取值一一列舉,
enum Day
{
Mon,
Tues,
Wed,
Thur,
Fri,
Sat,
Sun
};
enum Sex
{
MALE,
FEMALE
};
enum Color
{
RED=1,
GREEN=2,
BLUE=4
};
以上定義的 enum Day , enum Sex , enum Color 都是列舉型別, {}中的內容是列舉型別的可能取值,也叫列舉常量,
這些可能取值都是有值的,默認從0開始,一次遞增1,當然在定義的時候也可以賦初值,
三.聯合體
(1).聯合體介紹
聯合也是一種特殊的自定義型別, 這種型別定義的變數也包含一系列的成員,特征是這些成員公用同一塊空間(所以 聯合也叫共用體),
//聯合型別的宣告
union Un
{
char c;
int i;
};
//聯合變數的定義
union Un un;
union Un
{
int i;
char c;
};
int main()
{
union Un un;
// 下面輸出的結果是一樣的嗎?
printf("%p\n", &(un.i));
printf("%p\n", &(un.c));
//下面輸出的結果是什么?
un.i = 0x11223344;
un.c = 0x55;
printf("%x\n", un.i);
}
因為聯合體的成員公用一塊空間,所以地址相同,改變 un.c 也在改變 un.i ,根據小端存盤模式可知,列印結果為 11223355
在前面講解資料在記憶體中的存盤時,已經講解過一種判斷大小端的方法,今天我們還可以使用聯合體的方式去判斷
#include<stdio.h>
union Un
{
int i;
char c;
};
int main()
{
union Un un;
un.i = 1;
if (un.c == 1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
}
(2).聯合體的計算
(1). 聯合體的成員是共用同一塊記憶體空間的,這樣一個聯合變數的大小,至少是最大成員的大小(因為聯合至少得有 能力保存最大的那個成員)
(2).當最大成員大小不是最大對齊數的整數倍的時候,就要對齊到最大對齊數的整數倍,
union Un1
{
char c[5]; // 對齊數為 1 5個位元組
int i; // 對齊數為 4 4個位元組
};
union Un2
{
short c[7]; // 對齊數為 2 14個位元組
int i; // 對齊數為 4 4個位元組
};
//下面輸出的結果是什么?
printf("%d\n", sizeof(union Un1));
printf("%d\n", sizeof(union Un2));
Un1最大成員的大小為 5 個位元組,不是最大對齊數 4 的整數倍,因此應為 8 個位元組
Un2最大成員的大小為 14 個位元組,不是最大對齊數 4 的整數倍,因此應為 16 個位元組
// 輸出結果是什么?
#include<stdio.h>
int main()
{
union
{
short k;
char i[2];
}*s, a;
s = &a;
s->i[0] = 0x39;
s->i[1] = 0x38;
printf(“%x\n”,a.k);
return 0;
}
改變 char 陣列的值就是在改變 k 的值,因此 k 的值以 %x 的形式列印出來為 3839
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/267422.html
標籤:其他
