C - 基礎(chǔ)總結(jié)

1. 程序運(yùn)行模式

當(dāng)我們將一個(gè)程序交給CPU去執(zhí)行的時(shí)候,CPU只會(huì)執(zhí)行main函數(shù)中的代碼睬棚,別的地方的代碼是不會(huì)執(zhí)行的,因此如果想要在CPU中執(zhí)行程序就必須要在main函數(shù)中從上到下一句一句執(zhí)行代碼完慧,并且只有在上一句執(zhí)行完畢之后才會(huì)執(zhí)行下一句黎泣。
mian是程序的入口,當(dāng)mian函數(shù)中的代碼執(zhí)行完畢之后就會(huì)自動(dòng)結(jié)束必尼,所以也是出口蒋搜。

2. 計(jì)算機(jī)三大件

CPU : 中央處理器,處理數(shù)據(jù)的判莉,負(fù)責(zé)計(jì)算豆挽,協(xié)調(diào)其他硬件相互和諧的工作。

內(nèi)存 :存儲(chǔ)數(shù)據(jù) 券盅,臨時(shí)帮哈,效率高,通過電路存儲(chǔ)锰镀,電子式娘侍。

硬盤 :存儲(chǔ)數(shù)據(jù) 咖刃,永久存儲(chǔ),效率低憾筏,效率和轉(zhuǎn)速有關(guān)嚎杨,機(jī)械式。

3. 程序是如何運(yùn)行的

程序本質(zhì)就是一對(duì)指令氧腰,程序存儲(chǔ)在硬盤之中枫浙,當(dāng)雙擊點(diǎn)開之后,CPU會(huì)先將程序復(fù)制到內(nèi)存之中容贝,然后CPU再去讀取內(nèi)存中程序的指令自脯。這是因?yàn)樵趦?nèi)存中CPU的讀取效率更高。
例如:播放器播放電影斤富,播放時(shí)是運(yùn)行在內(nèi)存中的膏潮,但是電影文件確實(shí)保存在硬盤中的,當(dāng)雙擊電影打開播放器满力,播放器運(yùn)行在內(nèi)存中焕参,然后播放器在去分段的讀取電影文件。

或者英雄聯(lián)盟這樣的大型游戲也不是將整個(gè)游戲拷貝到內(nèi)存中油额,而是只將exe文件拷貝到CPU中叠纷,然后需要什么文件就加載哪些文件,不用的就會(huì)釋放掉潦嘶。

4. 程序處理數(shù)據(jù)

  1. 要不要存涩嚣?
    程序自己是否要把這些數(shù)據(jù)存儲(chǔ)起來,對(duì)于用戶操作產(chǎn)生的數(shù)據(jù)掂僵,或者一會(huì)兒要用的數(shù)據(jù)可以存儲(chǔ)起來航厚,以便以后顯示方便快捷。
  2. 存到哪锰蓬?
    存儲(chǔ)到內(nèi)存中幔睬,因?yàn)槌绦蜃约壕驮趦?nèi)存當(dāng)中
  3. 如何將數(shù)據(jù)存儲(chǔ)在內(nèi)存之中?
    先在內(nèi)存中找一個(gè)位置芹扭,將數(shù)據(jù)放到這個(gè)位置中麻顶,當(dāng)想要使用數(shù)據(jù)的時(shí)候,只要找到這個(gè)位置就可以了舱卡。
    而每一個(gè)位置在內(nèi)存中都有一個(gè)獨(dú)一無二地址辅肾,16進(jìn)制表示,0x開頭轮锥。通過這個(gè)地址找到這個(gè)位置宛瞄,然而地址非常難記,所以給位置起個(gè)別名,通過別名找到位置份汗。
    因此在開辟空間的同時(shí),需要指定空間的別名和類型蝴簇,而變量就是內(nèi)存中用來存儲(chǔ)數(shù)據(jù)的空間杯活,那么變量名就是變量所代表的那塊空間的別名。所以熬词,變量的本質(zhì)就是內(nèi)存中存儲(chǔ)數(shù)據(jù)的那塊兒空間旁钧。
    聲明一個(gè)變量,實(shí)際上就是在內(nèi)存中開辟一塊指定類型和別名的空間

5. 內(nèi)存中的五大區(qū)域

內(nèi)存當(dāng)中分為五大區(qū)域
為什么要分區(qū)個(gè)區(qū)域互拾?雖然每一個(gè)區(qū)域都是用來存儲(chǔ)數(shù)據(jù)的歪今,但是不同的數(shù)據(jù)存儲(chǔ)在不同的區(qū)域,這樣不僅方便系統(tǒng)的管理颜矿,也可以使系統(tǒng)更快寄猩,更明確的找到要找的地址。

  1. 棧 - 專門用來存儲(chǔ)局部變量骑疆,所有的局部變量都是聲明在棧區(qū)域當(dāng)中田篇。
  1. 堆 - 允許程序員手動(dòng)的從堆申請(qǐng)空間來使用。程序員可以自己申請(qǐng)指定字節(jié)數(shù)的空間箍铭。
  2. BSS段 - 用來存儲(chǔ)未初始化的全局變量和靜態(tài)變量泊柬,聲明一個(gè)全局變量,如果我們沒有初始化诈火,在程序運(yùn)行最開始的時(shí)候兽赁,這個(gè)變量沒有初始化時(shí)是存儲(chǔ)在BSS段,初始化之后冷守,全局變量和靜態(tài)變量就會(huì)被放到常量區(qū)刀崖。
  3. 數(shù)據(jù)段/常量區(qū) - 用來存儲(chǔ)已經(jīng)初始化的全局變量、靜態(tài)變量教沾,還有常量數(shù)據(jù)
  4. 代碼段 - 用來存儲(chǔ)程序的代碼/指令蒲跨。

注意:我們堆中申請(qǐng)的字節(jié)空間,如果我們不主動(dòng)釋放授翻,那么系統(tǒng)是不會(huì)釋放的或悲,除非程序結(jié)束
在堆中申請(qǐng)字節(jié)空間的步驟 a. 申請(qǐng) -> b. 使用 -> c. 釋放
如何在堆區(qū)申請(qǐng)指定字節(jié)數(shù)的字節(jié)空間呢?C語言提供了三個(gè)函數(shù)用來申請(qǐng)空間堪唐。這三個(gè)函數(shù)聲明在<stdlib.h>的系統(tǒng)頭文件中巡语。

malloc()函數(shù)

malloc() 參數(shù)只有一個(gè):size_t類型的,也就是unsigned long淮菠。
表示在堆內(nèi)存中申請(qǐng)參數(shù)個(gè)連續(xù)的字節(jié)空間男公,返回值是void *表示沒有類型的指針。并且返回的是創(chuàng)建的空間中的第一個(gè)字節(jié)的地址合陵。
那么我們應(yīng)該使用什么類型的指針變量來保存malloc()返回的地址枢赔?
用什么類型去接受澄阳,那要看你想要如何去操作申請(qǐng)的這些字節(jié)空間。如果你想要4個(gè)字節(jié)4個(gè)字節(jié)去操作那么就要用 int * 類型去接收,如果想8個(gè)字節(jié)8個(gè)字節(jié)的去錯(cuò)做那么就用 double * 類型去接收踏拜。

所以: int *p = malloc(24); 就相當(dāng)于在堆內(nèi)存中創(chuàng)建了一個(gè)長(zhǎng)度為6的整型數(shù)組

注意:
1.在堆區(qū)申請(qǐng)的字節(jié)空間是從低地址向高地址申請(qǐng)碎赢,每次申請(qǐng)的字節(jié)地址都是從0開始的,并且每次申請(qǐng)的空間不一定是連續(xù)的速梗。但是每一次申請(qǐng)的指定個(gè)字節(jié)肮塞,這些字節(jié)一定是連續(xù)的。
2.在堆區(qū)申請(qǐng)的字節(jié)里面也是有值的姻锁,值是垃圾值枕赵,并且值不會(huì)自動(dòng)清零。
3.在向堆區(qū)申請(qǐng)字節(jié)空間的時(shí)候位隶,有可能會(huì)申請(qǐng)失敗拷窜,如果申請(qǐng)失敗,返回的指針就是NULL值钓试,所以我們?cè)谏暾?qǐng)空間之后装黑,最好進(jìn)行判斷 if(p1) 看是否申請(qǐng)成功。
4.申請(qǐng)的空間使用完畢之后弓熏,一定要進(jìn)行釋放 free(p1); 如果沒有free()恋谭,那么需要等程序結(jié)束之后這些空間才會(huì)被釋放。

calloc()

calloc() 作用:向堆區(qū)申請(qǐng)指定字節(jié)數(shù)的空間挽鞠。
參數(shù)1.多少個(gè)單位
參數(shù)2.每一個(gè)單位的字節(jié)數(shù)
例:callco(3,sizeof(int)); // 表示申請(qǐng)3個(gè)4字節(jié)數(shù)的空間疚颊。
同樣有可能申請(qǐng)失敗。與malloc()的優(yōu)勢(shì)信认,calloc()申請(qǐng)的字節(jié)材义,申請(qǐng)完之后,系統(tǒng)會(huì)將申請(qǐng)到的空間自動(dòng)清零

realloc()

realloc()作用:擴(kuò)容嫁赏。
當(dāng)我們申請(qǐng)的字節(jié)空間不夠用的時(shí)候其掂,我們可以使用realloc() 擴(kuò)容。
例:realloc(p1,4); 表示在p1后面申請(qǐng)4個(gè)字節(jié)空間潦蝇。
一般會(huì)在我們申請(qǐng)的空間后面擴(kuò)容款熬,但是如果我們申請(qǐng)的空間后面被占用了,或者不夠我們擴(kuò)容的空間攘乒,就會(huì)重新去尋找一塊新足夠的空間申請(qǐng)贤牛,并將原來的數(shù)據(jù)拷貝過來,原來的空間將被釋放则酝。

注意:我們只能操作我們申請(qǐng)到的字節(jié)空間殉簸,如果貿(mào)然操作其他字節(jié)空間,很有可能修改掉系統(tǒng)的數(shù)據(jù),造成嚴(yán)重問題般卑。

6. fputs()函數(shù)

作用: 將字符串?dāng)?shù)據(jù)輸出到指定的流中武鲁。
流: 標(biāo)準(zhǔn)輸出流->控制臺(tái)。文件流 --> 磁盤上的文件椭微。
使用格式: fputs(要輸出的字符串,指定的流);
1). 使用fputs函數(shù)將字符串?dāng)?shù)據(jù)輸出到標(biāo)準(zhǔn)輸出流洞坑,也就是控制臺(tái)
標(biāo)準(zhǔn)輸出流: 控制臺(tái). stdout
2). 將字符串存儲(chǔ)到文件中.
a. 要先聲明1個(gè)文件指針,指向磁盤上的文件蝇率。使用fopen函數(shù)可以創(chuàng)建1個(gè)指向文件的指針。

fopen函數(shù)的兩個(gè)參數(shù):
第1個(gè)參數(shù): 文件的路徑刽沾,代表創(chuàng)建的指針就指向這個(gè)文件本慕。
第2個(gè)參數(shù): 操作文件的模式,你要對(duì)這個(gè)文件做什么操作侧漓,必須要告訴他锅尘。
"w"  --> write  代表要向這個(gè)文件寫入內(nèi)容。
"r"  --> read   代表從這個(gè)文件中讀取數(shù)據(jù)布蔗。
"a"  --> apped  追加代表向這個(gè)文件中追加數(shù)據(jù)藤违。
當(dāng)操作模式是"w"的時(shí)候,如果文件不存在纵揍, 就會(huì)創(chuàng)建這個(gè)文件顿乒,如果文件存在,就會(huì)將原來的文件替換掉泽谨。
當(dāng)操作模式是"a"的時(shí)候璧榄,如果文件存在則追加。如果不存在就創(chuàng)建這個(gè)文件吧雹。

b. 使用fputs函數(shù)將字符串寫入到指定的文件流中骨杂。
fputs(字符串,文件指針);
c. 寫完之后,一定要記得使用fclose()函數(shù)將這個(gè)文件關(guān)閉雄卷。

7. fget()函數(shù)

作用: 從指定的流中讀取字符串搓蚪。
這個(gè)流可以是標(biāo)準(zhǔn)輸入流-->控制臺(tái),也可以是文件流丁鹉。
1). 使用fgets函數(shù)從標(biāo)準(zhǔn)輸入流中讀取數(shù)據(jù)妒潭。
使用fgets函數(shù)從控制臺(tái)接收用戶輸入字符串,scanf函數(shù)gets函數(shù)也可以實(shí)現(xiàn)這個(gè)功能鳄炉。

scanf的缺點(diǎn)
        a. 不安全.
        b. 輸入的空格會(huì)被認(rèn)為結(jié)束.
gets函數(shù)的缺點(diǎn).
        a. 不安全.
fgets函數(shù)的優(yōu)點(diǎn)
        a. 安全.
        b. 空格也會(huì)一并接收.

語法:

fgets(要將字符串存儲(chǔ)到哪1個(gè)數(shù)組中,最多接收多少個(gè)長(zhǎng)度的字符串,指定流);
第2個(gè)參數(shù): 如果參數(shù)為n 那么函數(shù)最多就接收n-1個(gè)長(zhǎng)度的字符串杜耙,這個(gè)參數(shù)一般情況下和第1個(gè)參數(shù)數(shù)組的長(zhǎng)度一致。
第3個(gè)參數(shù):流拂盯,stdin: 代表標(biāo)準(zhǔn)輸入流佑女,也就是鍵盤流從控制臺(tái)輸入。

為什么fgets函數(shù)是安全的?
1. 如果輸入的字符串的長(zhǎng)度大于等于了第2個(gè)參數(shù)n,只會(huì)接收前面的n-1個(gè)团驱,然后最后1個(gè)自動(dòng)是'\0'摸吠。這樣,就不會(huì)崩潰。
2. 如果輸入的字符串的長(zhǎng)度剛好等于n-1那就是剛好的嚎花。
3. 如果輸入的字符串的長(zhǎng)度小于了n-1寸痢,那么就會(huì)將我們最后輸入的換行字符'\n'一并的接收。然后后面才是'\0'結(jié)束符紊选。

2). 使用fgets函數(shù)從文件流中讀取數(shù)據(jù):

就是讀取磁盤上文件的內(nèi)容.
// 1. 創(chuàng)建1個(gè)讀取文件的文件流.
FILE* pFile = fopen("/Users/Itcast/Desktop/abc.txt", "r");
// 2. 準(zhǔn)備1個(gè)字符數(shù)組.準(zhǔn)備存儲(chǔ)讀取到的字符串?dāng)?shù)據(jù).
char content[50]; 
// 3. 使用fgets函數(shù)從指定的文件流中讀取.
fgets(content, 50, pFile);
// 4. 讀取成功:
printf("讀取的內(nèi)容是: %s\n",content);
// 5. 關(guān)閉文件流
fclose(pFile);  

8. const修飾基本數(shù)據(jù)類型的變量

const是1個(gè)關(guān)鍵字啼止,是來修飾變量的,也就是說在聲明變量的同時(shí)兵罢,可以使用const關(guān)鍵字來修飾献烦。
例: const int num = 10;
一般情況下來說,被const修飾的變量具備一定程度上的不可變性卖词,被const修飾的變量我們叫做只讀變量巩那。

const修飾基本數(shù)據(jù)類型的變量 int、double此蜈、float即横、char。

    1. const int num = 10;
    這個(gè)時(shí)候.num變量的值只能去取值,而不能去修改.
    2. int const num = 10;
    效果同上.

const修飾數(shù)組.

    1. const int arr[4] = {10,20,30,40};
        數(shù)組的元素的值不能修改.
    2. int const arr[4] = {10,20,30,40};
        效果同上.

const修飾指針;

    1.  const int* p1 = #
    無法通過p1指針去修改指針指向的變量的值裆赵,但是如果直接操作變量這是可以的东囚,并且指針變量的值可以改,可以把另外1個(gè)變量的地址賦值給這個(gè)指針顾瞪。
    2.  int const * p1 = #
         效果同上
    3.  int  * const p1 = #
         p1的值不能修改舔庶,但是可以通過p1去修改p1指向的變量的值。
    4.  int const  * const p1 = #
         既不能修改p1的值陈醒,也不能通過p1去修改p1指向的變量的值惕橙。

const的使用場(chǎng)景.

    1. const的特點(diǎn):
        被const修飾的變量,是只讀變量钉跷,只能取值而不能改值弥鹦。所以,const變量的值爷辙,至始至終都不會(huì)發(fā)生變化彬坏。因此當(dāng)某些數(shù)據(jù)是固定的,在整個(gè)程序運(yùn)行期間都不會(huì)發(fā)生變化膝晾,并且你也不允許別人去修改時(shí)栓始,可以使用const來修飾這個(gè)變量。
    3. 當(dāng)函數(shù)的參數(shù)是1個(gè)指針的時(shí)候血当,函數(shù)的內(nèi)部是有可能會(huì)修改實(shí)參變量的值的幻赚,那么這個(gè)時(shí)候禀忆,可以使用const修飾指針參數(shù),這樣函數(shù)內(nèi)部只會(huì)使用我們的值 絕對(duì)改不了參數(shù)的值落恼。

9. 結(jié)構(gòu)體

不同的數(shù)據(jù)類型的變量是用來保存不同類型的數(shù)據(jù)的箩退。而結(jié)構(gòu)體是我們自己定義的數(shù)據(jù)類型。并指定這個(gè)數(shù)據(jù)類型的變量由哪些小的變量和成的佳谦。
語法格式:

例:
struct Student
{
     char * name;
     int  age;
     float height;
};

這代表我們新創(chuàng)建了一個(gè)數(shù)據(jù)類型戴涝,這個(gè)數(shù)據(jù)類型的名稱叫做 struct Student
這個(gè)新類型是由1個(gè)char * 類型,一個(gè)int 類型钻蔑,一個(gè)float類型的小的標(biāo)量聯(lián)合而成的啥刻。然而只有類型是不夠的,還需要根據(jù)類型聲明變量咪笑。

聲明結(jié)構(gòu)體類型的變量:
struct Student Tom;

** 結(jié)構(gòu)體變量的初始化**
意義:為結(jié)構(gòu)體變量中的小變量賦值郑什。嚴(yán)格意義上是將地址賦值給小變量。結(jié)構(gòu)體變量中的小變量就叫做結(jié)構(gòu)體的成員蒲肋。

初始化語法 使用點(diǎn)語法。
結(jié)構(gòu)體變量名稱.成員 = 數(shù)據(jù);
Tom.name = @"Tom";

什么時(shí)候使用結(jié)構(gòu)體
當(dāng)要保存一個(gè)數(shù)據(jù)钝满,但是發(fā)現(xiàn)這個(gè)數(shù)據(jù)需要由其他小變量組成的兜粘,這個(gè)時(shí)候先使用結(jié)構(gòu)體類自定義這個(gè)數(shù)據(jù)類型由哪些小變量合成的,然后在根據(jù)這個(gè)結(jié)構(gòu)體類型聲明變量弯蚜,來保存數(shù)據(jù)孔轴。

結(jié)構(gòu)體注意點(diǎn)

  1. 一定要先聲明結(jié)構(gòu)體類型,然后在聲明結(jié)構(gòu)體變量碎捺。

  2. 結(jié)構(gòu)體變量也是變量所以可以批量聲明路鹰。
    struct Car{

    } BMWCar,BCCar,KDLKCar;
    
  3. 定義結(jié)構(gòu)體名稱要求每一個(gè)單詞的首字母大寫。

  4. 可以在聲明結(jié)構(gòu)體類型的時(shí)候聲明結(jié)構(gòu)體變量收厨。

  5. 匿名結(jié)構(gòu)體

    struct{
    // 匿名結(jié)構(gòu)體只能在聲明結(jié)構(gòu)體的同時(shí)創(chuàng)建變量晋柱,并且不能單獨(dú)的聲明變量
    }car1;
    

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

  1. 先聲明變量,在使用點(diǎn)語法一個(gè)一個(gè)賦值诵叁。
  2. 在聲明結(jié)構(gòu)體變量的同時(shí)雁竞,就為結(jié)構(gòu)體變量的成員初始化。(最常用)
  3. 只初始化部分成員拧额,按順序碑诉。
  4. 也可以指定成員初始化。
    struct Student jim = {.name = "jim",.age = 18};

結(jié)構(gòu)體變量成員的默認(rèn)值
聲明一個(gè)結(jié)構(gòu)體變量侥锦,如果沒有給結(jié)構(gòu)體變量成員賦值进栽,那么成員是有值的,是垃圾值恭垦。只要在聲明結(jié)構(gòu)體變量的同時(shí)快毛,為一個(gè)成員變量初始化格嗅,整個(gè)結(jié)構(gòu)體就會(huì)自動(dòng)初始化為0,就不在是垃圾值了祸泪。

結(jié)構(gòu)體類型的作用域
一般情況下結(jié)構(gòu)體類型都是定義在函數(shù)外面吗浩,已讓所有函數(shù)都可以使用。

結(jié)構(gòu)體變量之間的相互賦值
相同結(jié)構(gòu)體類型的結(jié)構(gòu)體變量是可以賦值的没隘。
結(jié)構(gòu)體變量之間賦值的原理:
將結(jié)構(gòu)體變量中的每一個(gè)成員的值懂扼,拷貝過來復(fù)制一份,然后重新賦值給目標(biāo)結(jié)構(gòu)體變量中對(duì)應(yīng)的成員右蒲。結(jié)構(gòu)體變量之間的賦值是值傳遞阀湿。

結(jié)構(gòu)體數(shù)組

struct 結(jié)構(gòu)體類型名稱 數(shù)組名[數(shù)組長(zhǎng)度]; 
可以存儲(chǔ)5個(gè)strut 結(jié)構(gòu)體類型名稱 的結(jié)構(gòu)體
struct Student students[5]; 
數(shù)組的類型是struct Student,可以存儲(chǔ)5個(gè)struct Student類型的變量瑰妄。

結(jié)構(gòu)體數(shù)組的初始化

students[0] = (struct Student) {"name",16}; // 需要轉(zhuǎn)化為結(jié)構(gòu)體類型陷嘴。
或者直接在聲明結(jié)構(gòu)體數(shù)組的時(shí)候,為結(jié)構(gòu)體賦值间坐。

結(jié)構(gòu)體數(shù)組長(zhǎng)度的計(jì)算

使用sizeof計(jì)算出數(shù)組占用的總字節(jié)數(shù)/ 每一個(gè)元素占用的字節(jié)數(shù)
sizeof(students)/ sizeof(struct Student)

結(jié)構(gòu)體指針

struct 結(jié)構(gòu)體類型名稱* 指針名;
struct Student* pStu;
聲明了一個(gè)pStu指針變量灾挨,這個(gè)指針變量的類型是struct Student *。
這個(gè)指針就只能指向 struct Student
pStu = &stu1;

使用竹宋±统危可以使用指針間接的訪問結(jié)構(gòu)體變量。

(*pStu).name;
(*結(jié)構(gòu)體指針名).成員
pStu -> name;
結(jié)構(gòu)體指針名->成員 

結(jié)構(gòu)體嵌套
結(jié)構(gòu)體是可以嵌套的蜈七,在一個(gè)結(jié)構(gòu)體內(nèi)部聲明另外一個(gè)結(jié)構(gòu)體即可秒拔。

結(jié)構(gòu)體與函數(shù)
作為參數(shù)
結(jié)構(gòu)體是自定義的數(shù)據(jù)類型,當(dāng)然可以作為參數(shù)飒硅,結(jié)構(gòu)體作為參數(shù)傳值是值傳遞砂缩,如果想要在函數(shù)中修改結(jié)構(gòu)體變量的值,可以使用結(jié)構(gòu)體指針三娩。

作為返回值
結(jié)構(gòu)題類型完全可以作為函數(shù)的返回值庵芭,在返回的時(shí)候直接將結(jié)構(gòu)體變量返回即可。如果返回結(jié)構(gòu)體變量的地址尽棕,需要將結(jié)構(gòu)體創(chuàng)建在堆區(qū)喳挑。

10. 枚舉

變量的取值只能是指定的幾個(gè)值當(dāng)中的任意一個(gè),除此之外其他不行滔悉,需要自己定義具備限定取值的類型伊诵。
作用:支持先創(chuàng)建一種數(shù)據(jù)類型,這個(gè)數(shù)據(jù)類型的變量的取值被限定回官。

語法結(jié)構(gòu):
enum Type
{
     Type1,
     Type2,
     Type3,
};

這個(gè)數(shù)據(jù)類型的名稱叫做 **enum Type **曹宴。可以聲明這個(gè)類型的變量歉提,這個(gè)變量中就只能存儲(chǔ)這其中指定的任意一個(gè)笛坦。

聲明枚舉類型的變量区转。

enum 枚舉類型名稱 變量名 = 枚舉類型限定的取值之一。

枚舉作用域
一般定義在函數(shù)外版扩,每一個(gè)枚舉值都對(duì)應(yīng)一個(gè)整形數(shù)废离,默認(rèn)為0,依次遞增礁芦。枚舉類型的變量蜻韭,無論什么類型 都占據(jù)4個(gè)字節(jié)。而枚舉變量中真正存儲(chǔ)的是柿扣,枚舉值對(duì)應(yīng)的整形的數(shù)肖方。所以使用%d輸出枚舉的值。

所以也可以直接為枚舉變量賦值整形變量未状。但是一般不建議這么做 俯画,可讀性降低。命名規(guī)范 首字母大寫司草,每一個(gè)單詞的首字母大寫
枚舉值名稱以枚舉類型名開頭

11.type define 類型定義

作用: 為一個(gè)已經(jīng)存在的數(shù)據(jù)類型取別名艰垂。
例:typedef int clint; 為int數(shù)據(jù)類型去了一個(gè)別名,叫做clint埋虹。這個(gè)時(shí)候clint 完全等價(jià)于int 材泄。
因此當(dāng)數(shù)據(jù)類型很長(zhǎng)的時(shí)候既可以為這個(gè)數(shù)據(jù)類型取一個(gè)短一點(diǎn)的別名。

typedefine 數(shù)據(jù)類型 數(shù)據(jù)類型別名;
typedefine 給結(jié)構(gòu)體和枚舉取別名

1.聲明結(jié)構(gòu)體類型的同時(shí)給結(jié)構(gòu)體區(qū)別名
typedefine struct Student
{
    

} Student;

2.最常用是為聲明匿名結(jié)構(gòu)體的同時(shí)  取一個(gè)短別名吨岭。
typedefine struct 
{

} Student;

3.枚舉同理
typedefine enum 
{

} Dreiction;

12. 預(yù)處理指令

C語言從編寫到編譯、鏈接峦树、執(zhí)行的流程
編譯做的事情

  1. 先執(zhí)行原文件中的預(yù)處理指令辣辫,如果有文件包含指令,就將文件的內(nèi)容拷貝到寫指令的地方魁巩。
  2. 檢查語法是否符合規(guī)范急灭,符合就生成.o目標(biāo)文件,就是.c 對(duì)應(yīng)的二進(jìn)制指令谷遂。如果不符合語法規(guī)范葬馋,就報(bào)錯(cuò)不生成.o目標(biāo)文件。
  3. 鏈接
    為.o的目標(biāo)文件添加啟動(dòng)代碼
    告訴編譯器要調(diào)用的函數(shù)在什么地方
    調(diào)用的時(shí)候去正確的地方找實(shí)現(xiàn)
  4. 鏈接成功以后.out文件運(yùn)行即可肾扰。

預(yù)處理指令
預(yù)處理指令以#開頭畴嘶,并且都是在編譯之前執(zhí)行。

預(yù)處理指令類型

  1. 文件包含指令 #include集晚。
  2. 宏定義:可以將一段代碼定義為一個(gè)標(biāo)識(shí)窗悯,使用這個(gè)標(biāo)識(shí)就代表這段代碼。
  3. 條件編譯指令:只編譯指定的C代碼為二進(jìn)制指令偷拔。

宏定義

#define 宏名 宏值
#define N 10 

會(huì)將C代碼中使用宏名的地方替換成宏值 過程叫做宏替換

宏值可以是任意語句蒋院,定義宏的時(shí)候亏钩,并不會(huì)去檢查與法,只有當(dāng)完成了宏替換的時(shí)候欺旧,才會(huì)去檢查替換以后的代碼是否符合語法規(guī)范姑丑。
如果宏值是一個(gè)表達(dá)式,那么宏值并不是表達(dá)式的值辞友,而是表達(dá)式本身栅哀。
如果宏值當(dāng)中包括一個(gè)變量名,那么在使用這個(gè)宏之前必須保證這個(gè)變量已經(jīng)存在踏枣。
無法通過賦值符號(hào)位宏賦值昌屉。因?yàn)楹旮揪筒皇亲兞俊?/p>

宏作用域
從定義宏的地方開始,后面的所有地方都可以使用這個(gè)宏茵瀑。就算這個(gè)宏定義在這個(gè)大括弧里面间驮,在這個(gè)后面,哪怕是大括弧的后面都可以使用马昨。
默認(rèn)情況下竞帽,宏從定義的地方一直到文件結(jié)束都可以使用,#undef可以讓宏提前失效

#undef N 
解除宏定義鸿捧,之后宏就不可以使用了 體現(xiàn)實(shí)效

字符串優(yōu)先屹篓,也就是字符串中不會(huì)識(shí)別宏。系統(tǒng)不會(huì)認(rèn)為是一個(gè)宏匙奴,而認(rèn)為是字符串的一部分堆巧。
宏的層層替換。一個(gè)宏值中可以使用另外一個(gè)宏名泼菌。

#define 和typedef的區(qū)別
#define 預(yù)處理指令 在預(yù)編譯的時(shí)候會(huì)把宏明替換成宏值谍肤,typedef運(yùn)行的時(shí)候才會(huì)執(zhí)行。
#define可以將任意的C代碼取一個(gè)表示名哗伯, typedef只能為數(shù)據(jù)類型取名字。

帶參數(shù)的宏
在定義宏的時(shí)候焊刹,宏名是可以帶參數(shù)的。在這個(gè)宏值當(dāng)中虐块,可以直接使用這個(gè)參數(shù)。

#define N(a)
// 如果使用的宏有參數(shù)贺奠,就必須在使用的時(shí)候?yàn)楹陚髦怠?N(10);

宏帶參數(shù)替換的原理
先將參數(shù)賦值,然后在將宏值里面用到參數(shù)的地方替換為值颁糟,最后宏替換航背,將值替換為宏名玖媚。

使用帶參數(shù)的宏注意點(diǎn)

  1. 宏不是函數(shù),所以宏的參數(shù)不需要添加類型說明今魔。
  2. 我們?cè)诙x宏的時(shí)候,編譯器是如何區(qū)分宏名和宏值的障贸。
    #define 宏名 宏值 宏名中不可以有空格错森,與參數(shù)之間也不可以有空格。
  3. 為帶參數(shù)的宏傳值的時(shí)候篮洁,是本色傳遞涩维,如果傳遞一個(gè)變量,并不是傳遞這個(gè)變量的值袁波,而是直接傳遞的就是這個(gè)變量的串瓦阐。
  4. 宏值一旦換行就認(rèn)為宏定義結(jié)束了,需要使用 \ 來拼接宏
  5. 宏只適合于少量的代碼篷牌。

條件編譯指令

  1. 預(yù)處理指令睡蟋, 在預(yù)編譯階段執(zhí)行。
  2. 作用:默認(rèn)情況下,我們所有的C代碼都會(huì)被編譯為二進(jìn)制代碼,條件編譯指令的作用疚漆,可以讓編譯器只編譯部分的代碼。
  3. #if #elif #endif 必須要有 #endif

#ifif語句的區(qū)別

  1. 條件編譯指令是一個(gè)預(yù)處理指令豺瘤,在預(yù)處理階段執(zhí)行,而if語句是C代碼听诸,在程序運(yùn)行的時(shí)候執(zhí)行。
  2. if語句無論如何全都要被編譯為二進(jìn)制指令蚕泽,條件編譯指令:只會(huì)將符合條件的C代碼編譯為二進(jìn)制指令晌梨。
  3. 條件編譯指令參數(shù)必須為宏。
#ifdef 宏名        
如果定義了宏名的宏 就編譯其中的代碼
#ifndef 宏名 
如果沒有定義宏名就來到這里须妻。
#endif

13. static 和 extern

C語言當(dāng)中的兩個(gè)關(guān)鍵字仔蝌,是用來修飾變量和函數(shù)的。
如果都沒有修飾 默認(rèn)是 extern 荒吏。

  1. static和extern修飾局部變量
    static修飾局部變量敛惊,那么這個(gè)變量就叫做靜態(tài)變量,靜態(tài)變量不在存儲(chǔ)在棧區(qū)绰更,而是存儲(chǔ)在常量區(qū)中瞧挤,當(dāng)函數(shù)執(zhí)行完畢之后锡宋,這個(gè)靜態(tài)變量不會(huì)被回收。
    當(dāng)?shù)谝淮螆?zhí)行這個(gè)函數(shù)的時(shí)候特恬,就會(huì)將這個(gè)靜態(tài)變量聲明在常量區(qū)执俩,第二次去執(zhí)行這個(gè)函數(shù)的時(shí)候役首,聲明靜態(tài)變量的這句話就不會(huì)在執(zhí)行了衡奥,而是直接略過远荠,直接使用靜態(tài)變量的值矮台。
    所以static修飾的靜態(tài)變量瘦赫,函數(shù)結(jié)束不會(huì)被回收确虱,仍然存在窘问,函數(shù)無論執(zhí)行多少次宜咒,這個(gè)靜態(tài)變量只有一份故黑。
    extern不能修飾局部變量场晶。

  2. static和extern修飾全局變量的效果
    一個(gè)全局變量诗轻,最完整的步驟也應(yīng)該分為兩步,1.先寫全局變量的聲明搔体,只定義而不賦值侦高。2.在寫全局變量的定義奉呛,定義全局變量并初始化瞧壮。
    全局變量可以只有聲明咆槽,如果這樣的話秦忿,那么這個(gè)全局變量的值背會(huì)編譯器自動(dòng)的去實(shí)現(xiàn)灯谣,會(huì)將這個(gè)全局變量自動(dòng)初始化為0。
    全局變量也可以只有定義而沒有聲明峻呛,但是這個(gè)時(shí)候钩述,這個(gè)全局變量的定義必須要在使用全局變量的函數(shù)的前面。
    全局變量的聲明要寫在.h文件中所禀,全局變量的實(shí)現(xiàn)要寫在.c文件中北秽。
    如果將全局變量定義在模塊之中贺氓,這個(gè)全局變量就必須要使用static或者extern來修飾
    static修飾全局變量辙培,這個(gè)全局變量只能在當(dāng)前 模塊訪問搀别。
    extern修飾全局變量歇父,這個(gè)全局變量就可以跨模塊訪問再愈。

  3. static和extern修飾函數(shù)的效果
    static修飾函數(shù) 函數(shù)只可以在當(dāng)前模塊訪問
    extern修飾函數(shù) 那么函數(shù)可以跨模塊調(diào)用

文中如果有不對(duì)的地方歡迎指出垂睬。我是xx_cc驹饺,一只長(zhǎng)大很久但還沒有二夠的家伙赏壹。

本文已在版權(quán)印備案疟暖,如需轉(zhuǎn)載請(qǐng)?jiān)L問版權(quán)印俐巴。92899035

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末欣舵,一起剝皮案震驚了整個(gè)濱河市劣光,隨后出現(xiàn)的幾起案子绢涡,更是在濱河造成了極大的恐慌雄可,老刑警劉巖数苫,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件箱残,死亡現(xiàn)場(chǎng)離奇詭異被辑,居然都是意外死亡敷待,警方通過查閱死者的電腦和手機(jī)榜揖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來妨猩,“玉大人壶硅,你說我怎么就攤上這事庐椒≡继福” “怎么了棱诱?”我有些...
    開封第一講書人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)靡菇。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么泳唠? 我笑而不...
    開封第一講書人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮脖母,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘讼积。我一直安慰自己舆绎,他們只是感情好们颜,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著茅坛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪则拷。 梳的紋絲不亂的頭發(fā)上贡蓖,一...
    開封第一講書人閱讀 52,262評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音煌茬,去河邊找鬼斥铺。 笑死,一個(gè)胖子當(dāng)著我的面吹牛坛善,可吹牛的內(nèi)容都是我干的晾蜘。 我是一名探鬼主播邻眷,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼剔交!你這毒婦竟也來了竭鞍?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤领追,失蹤者是張志新(化名)和其女友劉穎些膨,沒想到半個(gè)月后洼哎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體识补,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蝙斜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了阁苞。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片骚灸。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡交汤,死狀恐怖戒洼,靈堂內(nèi)的尸體忽然破棺而出曹仗,到底是詐尸還是另有隱情轨蛤,我是刑警寧澤澳窑,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布悲立,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏痪蝇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一弃揽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧拇泛,春花似錦、人聲如沸攒发。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至变隔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間盒音,已是汗流浹背竖配。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留里逆,地道東北人进胯。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像原押,于是被迫代替她去往敵國(guó)和親胁镐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 一、框架 1盯漂、Mac系統(tǒng)及常用工具颇玷、進(jìn)制;C數(shù)據(jù)類型、常量變量就缆、運(yùn)算符帖渠、表達(dá)式、格式化輸入輸出 2竭宰、關(guān)系運(yùn)算符空郊、邏...
    師景福閱讀 695評(píng)論 0 2
  • 注:這是第三遍讀《C語言深度解剖》,想想好像自從大學(xué)開始就沒讀完過幾本書切揭,其中譚浩強(qiáng)的那本《C語言程序設(shè)計(jì)(第四版...
    HavenXie閱讀 1,736評(píng)論 1 6
  • 原文地址:C語言函數(shù)調(diào)用棧(一)C語言函數(shù)調(diào)用棧(二) 0 引言 程序的執(zhí)行過程可看作連續(xù)的函數(shù)調(diào)用狞甚。當(dāng)一個(gè)函數(shù)執(zhí)...
    小豬啊嗚閱讀 4,628評(píng)論 1 19
  • 一、溫故而知新 1. 內(nèi)存不夠怎么辦 內(nèi)存簡(jiǎn)單分配策略的問題地址空間不隔離內(nèi)存使用效率低程序運(yùn)行的地址不確定 關(guān)于...
    SeanCST閱讀 7,818評(píng)論 0 27
  • “晚上我請(qǐng)你喝茶廓旬。我們一家人出去哼审,找一個(gè)安靜的茶吧≡斜” “詩(shī)韻已經(jīng)約我了涩盾,說帶我出去吃東西±常” 詩(shī)韻是我表妹春霍,按輩...
    吳黎暉閱讀 667評(píng)論 0 0