最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語言自定義類型全解析

 更新時間:2022年02月10日 11:27:59   作者:誠摯的喬治  
在C語言中自定義類型主要有結(jié)構(gòu)體類型、位段、枚舉類型、聯(lián)合體類型,自定義類型是面試常會碰到的內(nèi)容,今天我們來詳細了解一下它

前言

初學(xué)C語言

我們先接觸的都是內(nèi)置的類型

比如說int char short float double long等等

這一期就來聊一聊自定義類型的知識

結(jié)構(gòu)體類型

首先我們要知道什么是結(jié)構(gòu)體

結(jié)構(gòu)體就是各種值集合

這些值被稱作結(jié)構(gòu)體成員,這些成員可包括各種不同的類型

struct tag         //這里的struct是結(jié)構(gòu)體的關(guān)鍵字,tag是結(jié)構(gòu)體標簽,也就是結(jié)構(gòu)體的名稱
{
	number - list; //結(jié)構(gòu)體成員列表
}veriable-list;    //結(jié)構(gòu)體的變量 

結(jié)構(gòu)體的聲明

如果結(jié)構(gòu)體的標簽是student,我拿student來舉例子

結(jié)構(gòu)體的完整聲明

struct Student
{
    char name[20];//姓名
    char sex;//性別
    int age;//年齡
    int num;//學(xué)號
};   //這里的分號不能丟

結(jié)構(gòu)體的不完全聲明(匿名結(jié)構(gòu)體類型)

struct
{
	int a;
	char b;
	double c;
}s;   //這s不能省略

匿名結(jié)構(gòu)體的特點就是沒有結(jié)構(gòu)體標簽

但這樣寫用戶使用時只能使用一次,也就是說只能在結(jié)構(gòu)體聲明時就定義變量

因為你找不到結(jié)構(gòu)體標簽,就相當于找不到門牌號一樣,無法再對其定義一個變量

結(jié)構(gòu)體變量的定義與初始化

結(jié)構(gòu)體的定義大致分為三種情況

<1>結(jié)構(gòu)體聲明的同時定義

struct Student 
{
    char name[20];//姓名
    char sex[20];//性別
    int age;//年齡
}s={"zhangsan","nan",20};

<2>結(jié)構(gòu)體先聲明,再定義

#include<stdio.h>
struct Student
{
    char name[20];//姓名
    char sex;//性別
    int age;//年齡
    int num;//學(xué)號
};
 
 
int main()
{
    struct Student s = { "zhangsan",'w',20,111 };
	return 0;
}

<3>匿名結(jié)構(gòu)體定義

struct 
{
    char name[20];//姓名
    char sex[20];//性別
    int age;//年齡
} s = { "zhangsan","nan",20};

注意:結(jié)構(gòu)體初始化與數(shù)組相同,都必須整體進行賦值。

結(jié)構(gòu)體的自引用

struct Node //初始話鏈表
{
	int a;
	struct Node next;
};

結(jié)構(gòu)體的自引用就是結(jié)構(gòu)體再套用自己

學(xué)過數(shù)據(jù)結(jié)構(gòu)的朋友應(yīng)該知道這是初始化鏈表

不過這一個代碼有問題的

問題在于無法求出這個結(jié)構(gòu)體的大小,不清楚這個結(jié)構(gòu)體有多大,因為無法求出自引用的結(jié)構(gòu)體有多大

所有自引用的結(jié)構(gòu)體要用指針來訪問

struct Node //初始話鏈表
{
	int a;
	struct Node* next;
};

故就可以通過指針來訪問每一個結(jié)點

結(jié)構(gòu)體的訪問

當結(jié)構(gòu)體定義且變量初始化完成后,就可以通過操作符來訪問變量中的成員

當然,這里給出了兩個操作符

分別是? .操作符和 -> 操作符

當使用結(jié)構(gòu)體變量時,就用點操作符,當訪問結(jié)構(gòu)體指針變量就用箭頭操作符

(1)通過結(jié)構(gòu)體變量進行訪問:

printf("%s\n",s.name);

(2)通過結(jié)構(gòu)體指針進行訪問:

printf("%s\n",ps->name);

結(jié)構(gòu)體的傳參

函數(shù)的調(diào)用有時候需要傳一些參數(shù)

參數(shù)的類型可以是不同的類型,可以是數(shù)組,也可以是指針

同樣結(jié)構(gòu)體的傳參也可通過傳結(jié)構(gòu)體或者傳指針

傳結(jié)構(gòu)體

#include<stdio.h>  
struct tag
{
	int a;
	char b[20];
}s1 = { 100,"abcdef" };
void print()
{
	printf("%d", s1.a);
}
int main()
{
	print(s1);
	return 0;
}

傳地址

#include<stdio.h>
struct tag
{
	int a;
	char b[20];
}s2 = { 100,"abcdef" };
void print(struct tag*s2)
{
	printf("%d", s2->a);
}
int main()
{
	print(&s2);
	return 0;
}

我們要知道函數(shù)傳參是形參就是實參的臨時拷貝

參數(shù)是要壓棧的(向系統(tǒng)申請空間),既然是臨時拷貝,就會再次再棧上開辟空間,當實參足夠大時,顯然會浪費一定的空間和時間

相比較與傳結(jié)構(gòu)體,傳指針會更好?

結(jié)構(gòu)體的內(nèi)存對齊(強烈建議觀看)

在另外一篇文章詳細講過——C語言結(jié)構(gòu)體中內(nèi)存對齊的問題理解

位段

可能有人沒有聽過什么是位段

位段的結(jié)構(gòu)類型跟結(jié)構(gòu)體有些類似可以類似結(jié)構(gòu)體去學(xué)習(xí)

也可以說

位段是結(jié)構(gòu)體特殊的實現(xiàn)

位段的聲明

相較于結(jié)構(gòu)體,位段的聲明有兩點不同

<1>規(guī)定位段的成員的必須是int,unsigned int ,signed int (但是寫成char類型也沒什么大的問題)

<2>位段的成員后面有一個冒號和一個數(shù)字

struct A  //位段的聲明
{
	int _a : 2;
	int _b : 5;
	int _c : 10;
	int _d : 30;
};

位段的內(nèi)存管理

#include<stdio.h>
struct A
{
	int a : 2;
	int b : 5;
	int c : 10;
	int d : 30;
};
int main()
{
	
	printf("大小是%d字節(jié)", sizeof(struct A));
	return 0;
}

為什么位段的大小是八個字節(jié)呢?

成員內(nèi)包含的數(shù)字代表的是這個成員需要利用的內(nèi)存,單位是bit。

位段成員申請內(nèi)存時都是以四個字節(jié)或者一個字節(jié)單位(當成員是char類型時)

int a : 2; //申請4個字節(jié),也就是32個bit位,利用兩個還剩30個
int b : 5; //利用5個,還剩25個
int c : 10; //利用10個,還剩15個
int d : 30; //這里的十五不夠,所以再申請了4個字節(jié)

最終的結(jié)果就是八字節(jié)

但問題是,變量d利用的空間是留下的15個bit加上重新申請的空間呢

這個結(jié)果在不同的環(huán)境的結(jié)果是不同的,所以位段的跨平臺性比較差

位段使用的前提是你知道存儲的內(nèi)存大概有多大

就比如說年齡

十個bit位0111111111,最大值就可以達到1023

就不需要再申請一次利用一個int類型的空間大小

這就達到了節(jié)省內(nèi)存的作用,存在即合理

位段的應(yīng)用?

struct A
{
	char a : 3;
	char b : 4;
	char c : 5;
};
main()
{
	struct A s = { 0 };
	s.a = 10;
	s.b = 12;
	s.c = 3;
	return 0;
}

位段的跨平臺性

1.int位段被當成有符號數(shù)還是無符號數(shù)是不確定的,有時候系統(tǒng)會自動轉(zhuǎn)化為無符號整形。

2.位段中最大位的數(shù)目不能確定。(因為在早期的16位機器int最大16,而32位機器int最大32)

3.位段中的成員在內(nèi)存中從左向右分配,還是從右向左分配標準尚未定義。

意思當內(nèi)存一個字節(jié)00000000,存入01010,可能會出現(xiàn)00001010或者01010000

4.當一個結(jié)構(gòu)包含兩個位段,第二個位段成員比較大,無法容納于第一個位段剩余的位時,是 舍棄剩余的位還是利用,這是不確定的。

?枚舉類型

枚舉類型適用于可以一一列舉的類型

比如說星期、性別

枚舉類型的定義

enum Day   //星期
{
	//枚舉的可能取值
	Mon,
	Tues,
	Wed,
	Thir,
	Fri,
	Sta,
	Sun
};
enum Sex  //性別
{
	MALE,//0
	FEMALE,//1
	SECRET//2
};

枚舉類型是有初始值的

如果你沒賦予它初始值,就會默認從零開始,依次加一

枚舉類型賦予初始值

#include<stdio.h>
enum Sex  //性別
{
	MALE = 4,
	FEMALE=10,
	SECRET//
};
main()
{
	printf("%d %d %d", MALE,FEMALE,SECRET);
	return 0;
}

可以看到,其實默認的值是可以改的

當某個成員被賦予某個值的時候,后續(xù)的成員就在此基礎(chǔ)上加一

枚舉類型的優(yōu)點

1.相較于數(shù)字,枚舉增加代碼的可讀性和可維護性

2.和#define定義的標識符比較枚舉有類型檢查,更加嚴謹。

3.防止了命名污染(封裝)

4.便于調(diào)試

5.使用方便,一次可以定義多個常量

聯(lián)合體類型

聯(lián)合體類型也叫共用體

聯(lián)合體的定義

union Un  
{
	int a;
	char b;
};

union是聯(lián)合體關(guān)鍵字,Un是聯(lián)合體的標簽

聯(lián)合體的特點

共用體,顧名思義,這里的共用就是公用內(nèi)存

內(nèi)存的也可被折疊

#include<stdio.h>
union Un
{
	char c;
	int i;
};
int main()
{
	union Un u = {0};
	printf("%d\n", sizeof(u));
	printf("%p\n", &u);
	printf("%p\n", &(u.c));
	printf("%p\n", &(u.i));
	return 0;
}

他們有相同的地址

c和i存放在同一塊內(nèi)存空間上,修改c或者i都會影響到另一個成員。

?聯(lián)合體內(nèi)存大小的計算

<1>聯(lián)合體內(nèi)存大小是最大成員的大小

<2>最大成員的大小如果不是最大對齊數(shù)的整數(shù)倍,就會對齊到最大對齊數(shù)的整數(shù)倍

(聯(lián)合體也存在內(nèi)存對齊)

#include<stdio.h>
union Un1
{
	char c[5];  
	int i;
};          
//Un1成員最大成員大小5,最大對齊數(shù)是4,所以Un1的大小是8;
union Un2
{
	char c[7];
		int i;
};
//Un2成員最大成員大小7,最大對齊數(shù)是4,所以Un2的大小是8;
int main()
{
	printf("%d\n", sizeof(union Un1));
	printf("%d\n", sizeof(union Un2));
	return 0;
}

到此這篇關(guān)于C語言自定義類型全解析的文章就介紹到這了,更多相關(guān)C語言 自定義類型內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

综艺| 永定县| 宝坻区| 墨玉县| 阳江市| 若尔盖县| 文昌市| 海宁市| 延安市| 广东省| 洪泽县| 东台市| 民丰县| 喀喇沁旗| 迭部县| 凌源市| 合江县| 北辰区| 利辛县| 新丰县| 贡嘎县| 阜宁县| 连城县| 醴陵市| 香港 | 福鼎市| 图木舒克市| 华容县| 水城县| 华亭县| 九台市| 苏州市| 信阳市| 炉霍县| 类乌齐县| 天祝| 南木林县| 城步| 芒康县| 宜昌市| 从江县|