目錄
1.結(jié)構(gòu)體
1.1結(jié)構(gòu)體的介紹
1.2結(jié)構(gòu)體的聲明
1.3特殊聲明(匿名結(jié)構(gòu)體類(lèi)型)
1.4結(jié)構(gòu)體自引用
1.5結(jié)構(gòu)體變量的定義和初始化
1.6結(jié)構(gòu)體內(nèi)存對(duì)齊
1.7修改默認(rèn)對(duì)其數(shù)
2.位段
2.1什么是位段
2.2位段的內(nèi)存分配
3.枚舉
3.1枚舉的定義
3.2枚舉的優(yōu)點(diǎn)
4.聯(lián)合體(共用體)
4.1聯(lián)合體類(lèi)型的定義
4.2聯(lián)合體的特點(diǎn)
?4.3聯(lián)合體大小的計(jì)算
什么是自定義類(lèi)型?
在C語(yǔ)言中,我們可以使用結(jié)構(gòu)體(Struct),枚舉(Enum),聯(lián)合體(Union)來(lái)創(chuàng)建自定義的類(lèi)型。
1.結(jié)構(gòu)體
1.1結(jié)構(gòu)體的介紹
結(jié)構(gòu)體(Struct):結(jié)構(gòu)體是一種用戶(hù)定義的數(shù)據(jù)類(lèi)型,用于將不同類(lèi)型的數(shù)據(jù)組合在一起,形成一個(gè)新的復(fù)合類(lèi)型。結(jié)構(gòu)體由一組成員(member)組成,每個(gè)成員可以是不同的數(shù)據(jù)類(lèi)型,如整型、字符型、浮點(diǎn)型、指針等。結(jié)構(gòu)體的定義使用?struct
?關(guān)鍵字,然后指定結(jié)構(gòu)體的名稱(chēng)以及成員列表。
1.2結(jié)構(gòu)體的聲明
struct student
{
char name[20];
int age;
char sex[5];
char id[20]
};
在上述代碼中,我們定義了一個(gè)名為student的結(jié)構(gòu)體,包含了一個(gè)整形類(lèi)型和三個(gè)字符類(lèi)型的數(shù)組。
1.3特殊聲明(匿名結(jié)構(gòu)體類(lèi)型)
struct
{
int a;
float b;
float c;
}x;
在上述代碼中,省略了結(jié)構(gòu)體的標(biāo)簽——這就是匿名結(jié)構(gòu)體類(lèi)型。
1.4結(jié)構(gòu)體自引用
我們可以在結(jié)構(gòu)體中包含一個(gè)結(jié)構(gòu)體,如果包含的這個(gè)結(jié)構(gòu)體是該結(jié)構(gòu)體本身的結(jié)構(gòu)體指針即為結(jié)構(gòu)體的自引用。
struct student
{
int age;
char name[20];
struct student* s1;
};
1.5結(jié)構(gòu)體變量的定義和初始化
struct student
{
int age;
char name[20];
}s1,s2;//在聲明結(jié)構(gòu)體類(lèi)型時(shí)定義變量s1,s2
struct student s3;//定義結(jié)構(gòu)體變量s3
struct point
{
int x;
int y;
}p1={1,1};//結(jié)構(gòu)體嵌套初始化
struct point p2 = { 1,2 };//初始化
1.6結(jié)構(gòu)體內(nèi)存對(duì)齊
結(jié)構(gòu)體內(nèi)存對(duì)齊是用來(lái)計(jì)算結(jié)構(gòu)體的大小的
如何計(jì)算?
首先得掌握結(jié)構(gòu)體的對(duì)齊規(guī)則:
1. 第一個(gè)成員在與結(jié)構(gòu)體變量偏移量為0的地址處。
2. 其他成員變量要對(duì)齊到某個(gè)數(shù)字(對(duì)齊數(shù))的整數(shù)倍的地址處。
對(duì)齊數(shù) = 編譯器默認(rèn)的一個(gè)對(duì)齊數(shù) 與 該成員大小的較小值。
VS中默認(rèn)的值為8
Linux中沒(méi)有默認(rèn)對(duì)齊數(shù),對(duì)齊數(shù)就是成員自身的大小
3. 結(jié)構(gòu)體總大小為最大對(duì)齊數(shù)(每個(gè)成員變量都有一個(gè)對(duì)齊數(shù))的整數(shù)倍。
4. 如果嵌套了結(jié)構(gòu)體的情況,嵌套的結(jié)構(gòu)體對(duì)齊到自己的最大對(duì)齊數(shù)的整數(shù)倍處,結(jié)構(gòu)體的整
體大小就是所有最大對(duì)齊數(shù)(含嵌套結(jié)構(gòu)體的對(duì)齊數(shù))的整數(shù)倍。
實(shí)例:
struct S1
{
char c1;
int i;
char c2;
};
int main()
{
printf("%d \n", sizeof(struct S1));
return 0;
}
?
為什么存在內(nèi)存對(duì)齊?
大部分的參考資料都是如是說(shuō)的:
1. 平臺(tái)原因(移植原因):
不是所有的硬件平臺(tái)都能訪問(wèn)任意地址上的任意數(shù)據(jù)的;某些硬件平臺(tái)只能在某些地址處取某些特
定類(lèi)型的數(shù)據(jù),否則拋出硬件異常。
2. 性能原因:
數(shù)據(jù)結(jié)構(gòu)(尤其是棧)應(yīng)該盡可能地在自然邊界上對(duì)齊。
原因在于,為了訪問(wèn)未對(duì)齊的內(nèi)存,處理器需要作兩次內(nèi)存訪問(wèn);而對(duì)齊的內(nèi)存訪問(wèn)僅需要一次訪
問(wèn)。
總體來(lái)說(shuō):
結(jié)構(gòu)體的內(nèi)存對(duì)齊是拿空間來(lái)?yè)Q取時(shí)間的做法
1.7修改默認(rèn)對(duì)其數(shù)
#pragma pack(1)//設(shè)置默認(rèn)對(duì)齊數(shù)為1
struct S3
{
double d;
char c;
int i;
};
struct S4
{
char c1;
struct S3 s3;
double d;
};
#pragma pack ()//取消設(shè)置默認(rèn)對(duì)齊數(shù),還原為默認(rèn)
2.位段
2.1什么是位段
位段(Bitfields)是C語(yǔ)言中一種用于定義結(jié)構(gòu)體成員的技術(shù),它允許我們對(duì)結(jié)構(gòu)體中的數(shù)據(jù)進(jìn)行位級(jí)別的控制。
位段的目的是在結(jié)構(gòu)體成員中存儲(chǔ)各個(gè)字段(或位)的數(shù)據(jù),并利用較少的內(nèi)存空間。通常,在處理一些較小范圍的整數(shù)值時(shí),使用完整的字節(jié)或更大的數(shù)據(jù)類(lèi)型可能會(huì)浪費(fèi)內(nèi)存。
位段的聲明和結(jié)構(gòu)體是類(lèi)似的,有兩個(gè)不同:
1.位段的成員必須是 int、unsigned int 或signed int 。
2.位段的成員名后邊有一個(gè)冒號(hào)和一個(gè)數(shù)字
比如:
struct student
{
int _a : 2;
int _b : 5;
int _c : 10;
int _d : 30;
};
student就是一個(gè)位段類(lèi)型。那student的大小呢?
2.2位段的內(nèi)存分配
1. 位段的成員可以是 int unsigned int signed int 或者是 char (屬于整形家族)類(lèi)型
2. 位段的空間上是按照需要以4個(gè)字節(jié)( int )或者1個(gè)字節(jié)( char )的方式來(lái)開(kāi)辟的。
3. 位段涉及很多不確定因素,位段是不跨平臺(tái)的,注重可移植的程序應(yīng)該避免使用位段。
實(shí)例:
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;
3.枚舉
3.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 都是枚舉類(lèi)型。
{}中的內(nèi)容是枚舉類(lèi)型的可能取值,也叫 枚舉常量 。
這些可能取值都是有值的,默認(rèn)從0開(kāi)始,依次遞增1,當(dāng)然在聲明枚舉類(lèi)型的時(shí)候也可以賦初值。
例如:
enum Color//顏色
{
RED=1,
GREEN=2,
BLUE=4
};
3.2枚舉的優(yōu)點(diǎn)
為什么使用枚舉?
我們可以使用 #define 定義常量,為什么非要使用枚舉?
枚舉的優(yōu)點(diǎn):
1. 增加代碼的可讀性和可維護(hù)性
2. 和#define定義的標(biāo)識(shí)符比較枚舉有類(lèi)型檢查,更加嚴(yán)謹(jǐn)。
3. 便于調(diào)試
4. 使用方便,一次可以定義多個(gè)常量
4.聯(lián)合體(共用體)
聯(lián)合體是一種特殊的數(shù)據(jù)類(lèi)型,允許在相同的內(nèi)存位置存儲(chǔ)不同類(lèi)型的數(shù)據(jù)。與結(jié)構(gòu)體不同的是,聯(lián)合體中的各個(gè)成員共享相同的內(nèi)存空間。
4.1聯(lián)合體類(lèi)型的定義
//聯(lián)合體類(lèi)型的聲明
union Un
{
char c;
int i;
};
int main()
{
//聯(lián)合體變量的定義
union Un un;
//計(jì)算聯(lián)合體變量的大小
printf("%d\n", sizeof(un));
//打印結(jié)果為4
}
4.2聯(lián)合體的特點(diǎn)
聯(lián)合的成員是共用同一塊內(nèi)存空間的,這樣一個(gè)聯(lián)合變量的大小,至少是最大成員的大?。ㄒ?yàn)槁?lián)
合至少得有能力保存最大的那個(gè)成員)。
union Un
{
int i;
char c;
};
int main()
{
union Un un;
printf("%d \n", &(un.i));
printf("%d \n", &(un.c));
un.i = 1;
un.c = 2;
printf("%d \n", un.i);
return 0;
}
?實(shí)例:判斷當(dāng)前機(jī)器的大小端?
int Pd()
{
union
{
int i;
char c;
}un = { .i = 1 };
return un.c;
}
int main()
{
int ret = Pd();
if (ret == 1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-566079.html
?4.3聯(lián)合體大小的計(jì)算
聯(lián)合的大小至少是最大成員的大小。
當(dāng)最大成員大小不是最大對(duì)齊數(shù)的整數(shù)倍的時(shí)候,就要對(duì)齊到最大對(duì)齊數(shù)的整數(shù)倍。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-566079.html
到了這里,關(guān)于C語(yǔ)言自定義類(lèi)型詳解(保姆級(jí)教學(xué))的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!