欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言 自定義類型全面系統(tǒng)理解

 更新時間:2022年02月11日 09:51:44   作者:i跑跑  
在C語言中自定義類型主要有結(jié)構(gòu)體類型、位段、枚舉類型、聯(lián)合體類型,自定義類型是面試常會碰到的內(nèi)容,本篇文章帶你徹底解決自定義類型

一、結(jié)構(gòu)體

結(jié)構(gòu)體是不同類型變量的集合體

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

struct Book      
{
 char name[20];//名字
 int Price;//價格
 char Writer[5];//作者
 char Time[20];//日期
};    //注意分號不能丟

struct為結(jié)構(gòu)體關(guān)鍵字,Book為結(jié)構(gòu)體標簽,中間不同類型的變量為結(jié)構(gòu)體的成員。上述現(xiàn)在只是定義了一個結(jié)構(gòu)體類型struct Book。

局部結(jié)構(gòu)體變量

int main()
{
   struct Book B1; // B1為局部結(jié)構(gòu)體變量
   return 0;
}

全局結(jié)構(gòu)體變量

struct Book      
{
 char name[20];
 int Price;
 char Writer[5];
 char Time[20];
}B3,B4,B5;      //在結(jié)構(gòu)體類型后可連續(xù)定義多個全局結(jié)構(gòu)體變量
 
struct Book B2;   //B2為全局結(jié)構(gòu)體變量
 
int main()
{
   return 0;
}

2.特殊聲明

不完全聲明

//匿名結(jié)構(gòu)體類型--沒有結(jié)構(gòu)體標簽
struct
{
 int a;
 char b;
 float c;
}x;
//這樣的結(jié)構(gòu)體類型必須緊跟著定義結(jié)構(gòu)體變量
//后面不能定義變量

不完全聲明類型只能在定義使用一次,并且在vs中:

struct
{
 int a;
 char b;
 float c;
}x;
 
struct
{
 int a;
 char b;
 float c;
}* ps;
 
int main()
{
  ps=&x;      //編譯器默認兩者類型不兼容  //且是錯誤寫法
  return 0;
}

因此不完全聲明很少使用,不推薦。?

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

這里可以用鏈表的實現(xiàn)來理解:

struct Node
{
 int data;
 struct Node* next;  
};

這樣就實現(xiàn)了自己類型的對象找自己類型對象的方法,這就是結(jié)構(gòu)體的自引用。?

4.結(jié)構(gòu)體變量的初始化

以上面struct Book為例:

struct Book      
{
 char name[20];
 int Price;
 char Writer[5];
 char Time[20];
}; 
 
 
int main()
{
   struct Book B1={"三腳貓",50,“阿里”,“20081001”};
   //初始化要用大括號
   return 0;
}

嵌套結(jié)構(gòu)體的初始化:

struct Data
{
  int a;
  char b[6];
};
 
struct Book      
{
 struct Data D;
 char name[20];
 int Price;
 char Writer[5];
 char Time[20];
}; 
 
 
int main()
{
   struct Book B1={{4,"haha"},"三腳貓",50,"阿里","20081001"};
   //大括號里加大括號
   return 0;
}

5.結(jié)構(gòu)體內(nèi)存對齊?

計算結(jié)構(gòu)體在內(nèi)存中的大小

方法:

1. 第一個成員為起始,設(shè)從下標為0的地址開始向后存儲。

2. 其他成員變量要對齊到對齊數(shù)的整數(shù)倍的地址處。 對齊數(shù) = 編譯器默認的一個對齊數(shù)與 該成員大小的較小值。 VS中默認的值為8

3. 結(jié)構(gòu)體總大小為所有成員對齊數(shù)中最大對齊數(shù)的整數(shù)倍。

4. 如果嵌套了結(jié)構(gòu)體的情況,嵌套的結(jié)構(gòu)體對齊到自己的最大對齊數(shù)的整數(shù)倍處,結(jié)構(gòu)體的整體大小就是所有最大對齊數(shù)(含嵌套結(jié)構(gòu)體的對齊數(shù))的整數(shù)倍。

舉例說明:

#include <stdio.h>
struct S1
{
	char c1;
	int i;
	char c2;
};
 
struct S2
{
	char c1;
	char c2;
	int i;
};
 
int main()
{
	printf("%d\n", sizeof(struct S1));
	printf("%d\n", sizeof(struct S2));
	return 0;
}

分析:

嵌套結(jié)構(gòu)體

#include <stdio.h>
struct S1
{
	char c1;
	int i;
	char c2;
};
 
struct S2
{
	char c1;
	char c2;
	struct S1 s1;
	int i;
};
 
int main()
{
	printf("%d\n", sizeof(struct S1));
	printf("%d\n", sizeof(struct S2));
	return 0;
}

分析:

內(nèi)存對齊的存在,在平臺和性能兩方面,可以使訪問空間更加高效,用空間換取時間。

讓占用空間小的成員盡量集中在一起。

6.修改默認對齊數(shù)

#pragma pack(1)     //修改默認對齊數(shù)為1
 
//一般修改的對齊數(shù)為2^n

舉例說明:

#include <stdio.h>
#pragma pack(1)   //修改為1相當于取消了對齊,沒有優(yōu)化,在實際應(yīng)用中很少用
struct S1
{
	char c1;
	int i;
	char c2;
};
int main()
{
	printf("%d\n", sizeof(struct S1));  // 6
	return 0;
}

當默認對齊數(shù)被修改后,每個類型的對齊數(shù)都變?yōu)?,整體的最大對齊數(shù)也為1(相當于沒有對齊),整體大小是1的倍數(shù),則1+4+1=6。

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

當一個函數(shù)涉及到結(jié)構(gòu)體時,最好用傳址調(diào)用:

struct S
{
 int data[1000];
 int num;
};
struct S s = {{1,2,3,4}, 1000};
//結(jié)構(gòu)體傳參
void print1(struct S s)
{
 printf("%d\n", s.num);
}
//結(jié)構(gòu)體地址傳參
void print2(struct S* ps)
{
 printf("%d\n", ps->num);
}
int main()
{
 print1(s);  //傳結(jié)構(gòu)體
 print2(&s); //傳地址
 return 0;
}

傳址調(diào)用原因:

1.函數(shù)傳參的時候,參數(shù)是需要壓棧,會有時間和空間上的系統(tǒng)開銷。

2.如果傳遞一個結(jié)構(gòu)體對象的時候,結(jié)構(gòu)體過大,參數(shù)壓棧的的系統(tǒng)開銷比較大,所以會導致性能的下降。

二、位段

位段的聲明和結(jié)構(gòu)是類似的,有兩個不同:

1.位段的成員必須是整型。

2.位段的成員名后邊有一個冒號和一個數(shù)字。

舉例:

struct S
{
 int _a:2;
 int _b:5;
 int _c:20;
 int _d:25;
};

此時S就是一個位段類型

他的大小為8

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

分析:

下面我們來分析位段在內(nèi)存中的存儲:

注:若初始化的值大于給其指定的空間,則先會發(fā)生截斷(斷左取右),再進行存儲

位段是根據(jù)實際需求來進行開辟空間,目的是為了節(jié)省空間提高效率。

跨平臺問題:

1. int 位段被當成有符號數(shù)還是無符號數(shù)是不確定的。

2. 位段中最大位的數(shù)目不能確定。(16位機器最大16,32位機器最大32,寫成27,在16位機 器會出問題。

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

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

三、枚舉

就是把可能的取值一一列舉

枚舉類型的定義:

例子:

enum Day  //星期
{
 Mon,
 Tues,
 Wed,
 Thur,
 Fri,
 Sat,
 Sun
};

enum Day就是一個枚舉類型,{}中的內(nèi)容是枚舉類型的可能取值,也叫枚舉常量。

枚舉常量是有值的,默認從0開始,依次遞增。

int main()
{
   enum Day d=Mon;   //定義一個變量,賦予{}內(nèi)可能的取值。
   return 0;
}

在定義的時候也可以賦初值,后面的常量依次遞增一

枚舉的優(yōu)點?

1. 增加代碼的可讀性和可維護性

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

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

4. 便于調(diào)試

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

注:最好用枚舉常量給枚舉變量賦值,才不會出現(xiàn)類型上的差異。

舉例:

當用cpp來運行程序時會報錯,因為cpp對代碼的格式會更加嚴格

而c就可以運行過去

養(yǎng)成良好的代碼風格,做到認真嚴謹。

四、聯(lián)合

聯(lián)合也是一種特殊的自定義類型

1.聯(lián)合類型的定義

//聯(lián)合類型的聲明
union Un
{
 char c;
 int i;
};
//聯(lián)合變量的定義
union Un un;
//計算連個變量的大小
printf("%d\n", sizeof(un));

2.聯(lián)合的特點?

聯(lián)合的成員是共用同一塊內(nèi)存空間的,這樣一個聯(lián)合變量的大小,至少是最大成員的大小。

union Un
{
	int i;
	char c;
};
union Un un;
 
int main()
{
	printf("%d\n", &(un.i));
	printf("%d\n", &(un.c));
	return 0;
}

共用一塊空間,起始地址相同。

使用案例:

union Un
{
	int i;
	char c;
};
union Un un;
 
int main()
{
	//printf("%d\n", &(un.i));
	//printf("%d\n", &(un.c));
	un.i = 0x11223344;
	un.c = 0x55;
	printf("%x\n", un.i);
	return 0;
}

分析:

3.聯(lián)合大小的計算?

聯(lián)合的大小至少是最大成員的大小。

當最大成員大小不是最大對齊數(shù)的整數(shù)倍的時候,就要對齊到最大對齊數(shù)的整數(shù)倍。

舉例:

union Un1
{
	char c[5];
	int i;
};
union Un2
{
	short c[7];
	int i;
};
//下面輸出的結(jié)果是什么?
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)文章

  • C++函數(shù)的嵌套調(diào)用和遞歸調(diào)用學習教程

    C++函數(shù)的嵌套調(diào)用和遞歸調(diào)用學習教程

    這篇文章主要介紹了C++函數(shù)的嵌套調(diào)用和遞歸調(diào)用學習教程,是C++入門學習中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-09-09
  • C++實現(xiàn)數(shù)獨快速求解

    C++實現(xiàn)數(shù)獨快速求解

    這篇文章主要為大家詳細介紹了C++實現(xiàn)數(shù)獨快速求解的方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 淺析結(jié)束程序函數(shù)exit, _exit,atexit的區(qū)別

    淺析結(jié)束程序函數(shù)exit, _exit,atexit的區(qū)別

    在一個程序中最多可以用atexit()注冊32個處理函數(shù),這些處理函數(shù)的調(diào)用順序與其注冊的順序相反,也即最先注冊的最后調(diào)用,最后注冊的最先調(diào)用
    2013-09-09
  • C語言實現(xiàn)簡易學生管理系統(tǒng)

    C語言實現(xiàn)簡易學生管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)簡易學生管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • 淺析C++的引用與const指針與各種傳遞方式

    淺析C++的引用與const指針與各種傳遞方式

    這篇文章主要介紹了淺析C++的引用與const指針與各種傳遞方式的相關(guān)資料,需要的朋友可以參考下
    2017-08-08
  • C語言近萬字為你講透樹與二叉樹

    C語言近萬字為你講透樹與二叉樹

    樹是計算機算法最重要的非線性結(jié)構(gòu)。因為樹能很好地描述結(jié)構(gòu)的分支關(guān)系和層次特性,所以在計算機科學和計算機應(yīng)用領(lǐng)域有著廣泛的應(yīng)用。這篇文章我就帶大家一起了解一下樹、二叉樹這種結(jié)構(gòu),下篇文章會重點向大家介紹二叉樹的遍歷算法
    2022-05-05
  • C++ 情懷游戲掃雷的實現(xiàn)流程詳解

    C++ 情懷游戲掃雷的實現(xiàn)流程詳解

    掃雷是電腦上很經(jīng)典很經(jīng)典的傳統(tǒng)老游戲,從小編第一次摸到計算機開始就玩過掃雷,雖然當時并不理解玩法原理,但終是第一次玩電腦游戲,下面來從掃雷的前世今生講起
    2021-11-11
  • C語言編程中建立和解除內(nèi)存映射的方法

    C語言編程中建立和解除內(nèi)存映射的方法

    這篇文章主要介紹了C語言編程中建立和解除內(nèi)存映射的方法,分別為mmap()函數(shù)和munmap()函數(shù)的使用,需要的朋友可以參考下
    2015-08-08
  • QT編寫tcp通信工具(Client篇)

    QT編寫tcp通信工具(Client篇)

    這篇文章主要介紹了QT編寫tcp通信工具,適用于Client端,類似網(wǎng)上常見的網(wǎng)絡(luò)調(diào)試工具,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • 使用C++制作簡單的web服務(wù)器(續(xù))

    使用C++制作簡單的web服務(wù)器(續(xù))

    本文承接上文《使用C++制作簡單的web服務(wù)器》,把web服務(wù)器做的功能稍微強大些,主要增加的功能是從文件中讀取網(wǎng)頁并返回給客戶端,而不是把網(wǎng)頁代碼寫死在代碼中,有需要的小伙伴來參考下吧。
    2015-03-03

最新評論