tft每日頭條

 > 圖文

 > c基本語法結構

c基本語法結構

圖文 更新时间:2024-11-19 02:15:33
1. c 關鍵字

c基本語法結構(一文掌握C基本語法)1

2. 命名空間

變量、函數和後面要學到的類都是大量存在的,這些變量、函數和類的名稱将都存在于全局作用域中,可能會導緻很多沖突。

使用命名空間的目的是對标識符的名稱進行本地化,以避免命名沖突或名字污染,namespace關鍵字的出現就是針對這種問題的。

c基本語法結構(一文掌握C基本語法)2

2.1 命名空間定義

使用namespace關鍵字,後面跟命名空間的名字,然後用{}将成員括起來即可,和C語言的結構體類似

c基本語法結構(一文掌握C基本語法)3

存在多個相同的命名空間的時候,編譯器編譯的時候會把他們合并,如下面

c基本語法結構(一文掌握C基本語法)4

命名空間可以嵌套

c基本語法結構(一文掌握C基本語法)5

PS:命名空間定義了一個新的作用域,命名空間中的所有内容都局限于該命名空間中,但是成員的生命周期沒有改變,仍然是全局的。

2.2 命名空間使用

命名空間有3種使用方式

以下均使用該命名空間

c基本語法結構(一文掌握C基本語法)6

1.加命名空間名稱及作用域限定符

c基本語法結構(一文掌握C基本語法)7

這種方法每次使用的時候都要進行::限定,比較麻煩

2.使用using将命名空間中成員引入

c基本語法結構(一文掌握C基本語法)8

這樣就可以不用::限定命名空間,直接使用b

3.使用using namespace 命名空間名稱引入

c基本語法結構(一文掌握C基本語法)9

可以使用所有N中内容,但是需要注意的是這樣可能會造成名稱沖突

3. C 輸入&輸出

c基本語法結構(一文掌握C基本語法)10

1. 使用cout标準輸出(控制台)和cin标準輸入(鍵盤)時,必須包含< iostream >頭文件以及std标準命名空間。

2. 使用C 輸入輸出更方便,不需增加數據格式控制

c基本語法結構(一文掌握C基本語法)11

4. 缺省參數

缺省參數就像女神的備胎,當女神有男朋友的時候,備胎被冷落在一旁,當女神分手後,備胎才可以派上用場。

4.1 缺省參數概念

缺省參數是聲明或定義函數時為函數的參數指定一個默認值。在調用該函數時,如果沒有指定實參則采用該默認值,否則使用指定的實參。

c基本語法結構(一文掌握C基本語法)12

c基本語法結構(一文掌握C基本語法)13

4.2 缺省參數分類

全缺省參數

c基本語法結構(一文掌握C基本語法)14

半缺省參數

c基本語法結構(一文掌握C基本語法)15

注意:

1. 半缺省參數必須從右往左依次來給出,不能間隔着給2. 缺省參數不能在函數聲明和定義中同時出現,且應隻出現于聲明

c基本語法結構(一文掌握C基本語法)16

3. 缺省值必須是常量或者全局變量

5. 函數重載

自然語言中,一個詞可以有多重含義,人們可以通過上下文來判斷該詞真實的含義,即該詞被重載了。

比如:有兩個體育項目大家根本不用看,也不用擔心。一個是乒乓球,一個是男足。前者是“誰也赢不了!”,後者是“誰也赢不了!”

c基本語法結構(一文掌握C基本語法)17

5.1 函數重載概念

函數重載:是函數的一種特殊情況,C 允許在同一作用域中聲明幾個功能類似的同名函數,這些同名函數的形參列表(參數個數 或 類型 或 順序)必須不同,常用來處理實現功能類似數據類型不同的問題。

下面都是函數重載:

c基本語法結構(一文掌握C基本語法)18

下面這兩個不是函數重載!

c基本語法結構(一文掌握C基本語法)19

5.2 名字修飾

那麼為什麼C 支持函數重載而C語言不支持呢?

一個程序要運行起來要經曆以下幾步:假設有以下文件

f.h f.cpp test.cpp

1.預處理——頭文件展開,宏替換,條件編譯,去掉注釋

生成f.i test.i

2.編譯——檢查語法,生成彙編代碼

生成f.s test.s

3.彙編——把彙編代碼轉換成二進制的機器碼(讓CPU能看懂)

生成f.o test.o

4.鍊接——找調用函數的定義地址,鍊接對應上,合并到一起

生成a.out可執行程序

在鍊接階段,編譯器看到test.o調用了哪些函數,就會去f.o的符号表中找對應函數的地址,然後鍊接在一起,那麼要怎麼去找呢?C 和C語言采用了不同的名字修飾,就會用不同的名字去找

c基本語法結構(一文掌握C基本語法)20

我們發現名字由_Z 函數名長度 函數名首字母 函數按順序參數首字母,因此支持函數重載(名字不一樣,找的對象就不一樣)C:

c基本語法結構(一文掌握C基本語法)21

這裡我們發現C語言則是直接用函數名作為地址查找對象,回想我們的函數指針,是不是函數指針和函數名都可以調用函數呢。因此如果C語言中出現函數重載,那麼調用的時候就會查找到兩個不同地址,C語言不知道要鍊接哪一個,因此出錯。

5.3 extern “C”

我們知道C語言可以調用C語言的靜态庫和動态庫,C 可以調用C 的靜态庫和動态庫,那麼C 能不能調用C的庫?C能不能調用C 的庫?

答案是可以的。

我們先來看C 調用C的庫,這裡我們用C語言實現的棧的代碼生成一個靜态庫

c基本語法結構(一文掌握C基本語法)22

再新開一個項目,調用這個庫,這裡對新項目的屬性進行更改。

c基本語法結構(一文掌握C基本語法)23

c基本語法結構(一文掌握C基本語法)24

然後來看一下現在能否調用

c基本語法結構(一文掌握C基本語法)25

這是不是意味着C 不能調用C的庫?别急,這時候extern C就登場了

c基本語法結構(一文掌握C基本語法)26

我們發現加了這個關鍵字後就鍊接成功了。這個關鍵字的意思是告訴編譯器将該部分按照C語言的規則來進行編譯,我們調用C庫,當然就要按C的規則來啦。

再來看一下C語言能否調用C 的庫,我們把後綴名更改一下

c基本語法結構(一文掌握C基本語法)27

c基本語法結構(一文掌握C基本語法)28

c基本語法結構(一文掌握C基本語法)29

(這裡是c語言了,因此隻能用typedef過的别名,不能再用一個Stack,因為C語言不支持) 好像不行,我們剛剛是在C 的部分進行修改,這次我們也在C 的部分進行修改,我們來到test_01,對頭文件部分的聲明進行如下修改。

c基本語法結構(一文掌握C基本語法)30

c基本語法結構(一文掌握C基本語法)31

這樣是不是就順利鍊接成功了,這裡的預編譯進行了判斷,如果文件是C 的,那麼就用C的規則進行編譯,也可以這麼寫:

c基本語法結構(一文掌握C基本語法)32

6. 引用6.1 引用概念

引用不是新定義一個變量,而是給已存在變量取了一個别名,編譯器不會為引用變量開辟内存空間,它和它引用的變量共用同一塊内存空間。

類型& 引用變量名(對象名) = 引用實體;

c基本語法結構(一文掌握C基本語法)33

引用類型必須和引用實體是同種類型的

6.2 引用特性

1. 引用在定義時必須初始化2. 一個變量可以有多個引用3. 引用一旦引用一個實體,再不能引用其他實體

6.3 常引用

c基本語法結構(一文掌握C基本語法)34

這裡我們取别名的規則是:

對原引用變量,權限隻能縮小,不能放大。這裡權限指的是讀寫權限。

因此對const常量隻能進行讀,也就隻能用const引用。

在下面将double賦給int别名的過程中,編譯器會産生“臨時變量”,将double d中整數部分賦給臨時變量, 這個臨時變量再将這個整數賦給另一個int類型的臨時變量,最後int把臨時變量賦給rd,也就是說rd引用的其實是這個int臨時變量,而臨時變量具有常屬性,因此要用const引用。

6.4 使用場景

1.作函數參數

c基本語法結構(一文掌握C基本語法)35

在學習C語言的時候我們如果要交換兩個數,那麼就需要傳址調用函數,而現在可以直接用引用進行修改,這就是引用做參數的好處,輸出型參數另外,如果是傳值調用的話,我們知道形參是實參的一個臨時拷貝,而傳引用的時候并沒有拷貝這一步,這就提高了效率

2.作函數返回值

c基本語法結構(一文掌握C基本語法)36

結果是顯然的,我們返回的是靜态變量n的别名,而出了函數作用域n并沒有銷毀,那麼來看下面這個代碼

c基本語法結構(一文掌握C基本語法)37

c基本語法結構(一文掌握C基本語法)38

c基本語法結構(一文掌握C基本語法)39

n和ret地址一樣

這裡n不再是靜态變量了,出了函數作用域後空間返還,而我們的ret是n的别名,這是不是就相當于野指針。因此隻有第一次調用函數後ret中的值是1,調用一次函數(函數重載<<)後n的空間被制成随機數,因此剩下兩次都是随機數,因此我們用引用作返回值的時候返回的應該是出了函數定義域還存在的變量的引用,否則就應該按值返回,這裡和指針是一個道理。

明白了這些下面這個程序的結果就應該很明确了,應該是7

c基本語法結構(一文掌握C基本語法)40

c基本語法結構(一文掌握C基本語法)41

道理是一樣的。另外引用作返回值也會提高效率

6.5 傳值、傳引用效率比較

以值作為參數或者返回值類型,在傳參和返回期間,函數不會直接傳遞實參或者将變量本身直接返回,而是傳遞實參或者返回變量的一份臨時的拷貝,因此用值作為參數或者返回值類型,效率是非常低下的,尤其是當參數或者返回值類型非常大時,效率就更低。

這裡用程序來比較一下

c基本語法結構(一文掌握C基本語法)42

c基本語法結構(一文掌握C基本語法)43

不是很明顯的原因是我們計算機的速度實在太快,但是還是有效率差異的。

c基本語法結構(一文掌握C基本語法)44

c基本語法結構(一文掌握C基本語法)45

指針和引用的效率是一樣的,因為引用的底層和指針的底層是一樣的!

6.6 引用和指針的區别

從語法概念上:引用是别名,沒有額外開空間,而指針存儲變量的地址,開辟了4/8字節的空間

從底層實現的角度:引用實際上是有空間的,因為引用是按指針的方式來實現的

來看一下指針和引用的彙編

c基本語法結構(一文掌握C基本語法)46

彙編指令完全一樣,也印證了底層是一樣的

那引用和指針的不同點是什麼呢?

1. 引用在定義時必須初始化,指針沒有要求

2. 引用在初始化時引用一個實體後,就不能再引用其他實體,而指針可以在任何時候指向任何一個同類型實體

3. 沒有NULL引用,但有NULL指針

4. 在sizeof中含義不同:引用結果為引用類型的大小,但指針始終是地址空間所占字節個數(32位平台下占4個字節)

5. 引用自加即引用的實體增加1,指針自加即指針向後偏移一個類型的大小

6. 有多級指針,但是沒有多級引用

7. 訪問實體方式不同,指針需要顯式解引用,引用編譯器自己處理

8. 引用比指針使用起來相對更安全

7. 内聯函數

7.1 概念

以inline修飾的函數叫做内聯函數,編譯時C 編譯器會在調用内聯函數的地方展開,沒有函數壓棧的開銷,内聯函數提升程序運行的效率。

在學習C語言的時候,我們遇到函數體短小且頻繁調用的函數的時候,采用的優化方式是使用宏進行替換,但是宏太繁瑣啦,難以看懂,因此c 就産生了内聯函數。

那麼内聯函數是如何進行優化的呢?來看代碼。

c基本語法結構(一文掌握C基本語法)47

當我們不用inline定義函數的時候,函數是怎麼調用的呢?

c基本語法結構(一文掌握C基本語法)48

進行函數壓棧,然後用call指令調用。那麼用了inline後呢

c基本語法結構(一文掌握C基本語法)49

我們發現在彙編代碼中直接對函數調用的代碼進行了替換,沒有壓棧和call調用指令。

7.1 特性

1. inline是一種以空間換時間的做法,省去調用函數額開銷。所以代碼很長或者有循環/遞歸的函數不适宜使用作為内聯函數。

2. inline對于編譯器而言隻是一個建議,編譯器會自動優化,如果定義為inline的函數體内有循環/遞歸等等,編譯器優化時會忽略掉内聯。

3. inline不建議聲明和定義分離,分離會導緻鍊接錯誤。因為inline被展開,就沒有函數地址了,鍊接就會找不到。

例如如果在.h和.cpp文件中分别聲明和定義内聯函數,那麼在鍊接的時候就會出現錯誤:main.obj : error LNK2019: 無法解析的外部符号 "void __cdecl f(int)" (?f@@YAXH@Z),該符号在函數 _main 中被引用

那麼内聯函數相比宏有哪些優點?

1.内聯函數在debug版本下支持調試,而宏不支持

2.内聯函數就是普通函數的寫法,解決了宏晦澀難懂的問題

c基本語法結構(一文掌握C基本語法)50

8. auto關鍵字(C 11)

8.1 auto簡介

在早期C/C 中auto的含義是:使用auto修飾的變量,是具有自動存儲器的局部變量

C 11中,标準委員會賦予了auto全新的含義即:auto不再是一個存儲類型指示符,而是作為一個新的類型指示符來指示編譯器,auto聲明的變量必須由編譯器在編譯時期推導而得。

c基本語法結構(一文掌握C基本語法)51

使用auto定義變量時必須對其進行初始化,在編譯階段編譯器需要根據初始化表達式來推導auto的實際類型。因此auto并非是一種“類型”的聲明,而是一個類型聲明時的“占位符”,編譯器在編譯期會将auto替換為變量實際的類型。

8.2 auto的使用細則

1.用auto聲明指針類型時,用auto和auto*沒有任何區别,但用auto聲明引用類型時則必須加&

c基本語法結構(一文掌握C基本語法)52

c基本語法結構(一文掌握C基本語法)53

2. 在同一行定義多個變量當在同一行聲明多個變量時,這些變量必須是相同的類型,否則編譯器将會報錯,因為編譯器實際隻對第一個類型進行推導,然後用推導出來的類型定義其他變量。

c基本語法結構(一文掌握C基本語法)54

c基本語法結構(一文掌握C基本語法)55

8.3 auto不能推導的場景

1. auto不能作為函數的參數

c基本語法結構(一文掌握C基本語法)56

2. auto不能直接用來聲明數組

c基本語法結構(一文掌握C基本語法)57

3. 為了避免與C 98中的auto發生混淆,C 11隻保留了auto作為類型指示符的用法4. auto在實際中最常見的優勢用法就是C 11提供的新式for循環,還有lambda表達式等進行配合使用。

c基本語法結構(一文掌握C基本語法)58

c基本語法結構(一文掌握C基本語法)59

9. 基于範圍的for循環(C 11)9.1 範圍for的語法

for循環後的括号由冒号“ :”分為兩部分:第一部分是範圍内用于叠代的變量,第二部分則表示被叠代的範圍。

c基本語法結構(一文掌握C基本語法)60

範圍for循環與普通循環類似,可以用continue來結束本次循環,也可以用break來跳出整個循環。

9.2 範圍for的使用條件

1. for循環叠代的範圍必須是确定的對于數組而言,就是數組中第一個元素和最後一個元素的範圍;對于類而言,應該提供begin和end的方法,begin和end就是for循環叠代的範圍。

c基本語法結構(一文掌握C基本語法)61

2. 叠代的對象要實現 和==的操作。

10. 指針空值nullptr(C 11)10.1 C 98中的指針空值

c基本語法結構(一文掌握C基本語法)62

在傳統頭文件中有如上定義,我們發現在C 中Null被宏替換為0,而如果我們要對一個指針賦空值,仍采用NULL的話有些不妥,因為0畢竟是一個數字,而不是指針類型,因此C 11引入了nullptr,其實也就相當于(void*)0。

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关圖文资讯推荐

热门圖文资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved