C 關鍵字總結

2021-07-28 09:23:46 字數 4680 閱讀 9919

const 與define

define是預編譯器的編譯指令,它從c語言相容下來,工作方式與文字編輯器中的全域性搜尋和替換相似。define定義的常量的意義在它開始的地方持續到檔案結束,在預編譯階段,預編譯器已經將所有define刪除,並展開所有的巨集定義。它單純只做文字替換,沒有型別安全檢查,define命令會很容易引入錯誤,並且這種錯誤很難發覺,因此c++中用const取代define預編譯指令。

#define sigmoid(x) (1/(1+exp(-x)))

result = sigmoid(a+b);//沒有正確新增括號,會導致錯誤結果

result = sigmoid((a+b));//正確

標頭檔案裡的const

const預設是內部鏈結,如果它被放在標頭檔案中,目的是為了讓所有包含它的編譯單元能使用這個值,而且是僅讓包含標頭檔案的編譯單元可見。定義乙個const時,必須初始化,除非用extern做出了外部引用。通常,c++編譯器不會為const變數分配空間,但extern關鍵字會強制編譯器為const變數分配儲存空間。因為extern為外部鏈結,為了其他的編譯單元都能引用到const變數。變數必須要有儲存空間。

:由於編譯器不能避免為const分配記憶體,所以const定義必須預設內部鏈結。在c++中,const常量是否被分配空間依賴於它如何被使用:對於基本資料型別的常量,編譯器會把它放到目標檔案的符號表中而不分配儲存空間,而自定義的const物件則需要分配儲存空間(大物件)。還有一些情況下也需要分配儲存空間,例如強制宣告為extern或取乙個const的位址等操作。

const關鍵字與多執行緒安全

可重入是併發安全的保障,乙個可重入的函式(函式沒有執行完成,由於外部因素或內部呼叫,又一次進入函式執行)在多執行緒的環境下可以放心使用。而為了保證乙個函式是可重入的,它必須使用任何(區域性)靜態或非const全域性變數。同時,不能返回任何(區域性)靜態或非const全域性變數的指標。

類中的const

在類中定義的非靜態const變數,這個類的不同的物件可以含有乙個不同的值。const的初始化在類的建構函式的初始化列表中。

static const——編譯期間類裡的專屬常量

static意味著「不管類的物件被建立多少次,都只有乙個例項」。必須在static const定義的地方對它初始化。c++用它來代替enum(列舉型),來指示物件的共同屬性。它是為整個類服務,而不是某個物件,所以它不能使用this指標(this指標是對成員函式呼叫時用來指示呼叫物件的),也不能在複製建構函式中被複製。如果你取某個類的專屬常量的位址或編譯器堅持要看到乙個定義式,則用網域名稱解析符定義一下

class gameplayer;

中const

int gameplayer::numturns;//numturns在class宣告中已經初始化,因此這裡不再設初值

const物件和成員函式

不修改資料成員的任何函式都應該宣告為const,這樣它可以和const物件一起使用。

按位const:物件中的每個位元組都不能變。

按邏輯const:可以以成員為單位改變。

兩種實現按邏輯const的方法

一種是取this指標,並把它強制轉換成指向當前型別物件的指標,具體來說就是講將this強制轉換成普通指標。

另一種是使用關鍵字mutable,以指定乙個特定的資料成員可以在乙個const物件中被改變。

static關鍵字有兩個作用,乙個讓變數存在靜態區,另乙個是讓錯誤限制在乙個原始檔內。讓區域性變數宣告成static使區域性變數儲存在靜態區,從而在程式的整個生命期都存在。同時,當static作用於全域性變數時,該全域性變數變為內部鏈結,它的意思是「在檔案的外部不可以使用這個名字」,從而使錯誤區域性化。

static全域性變數與全域性變數的區別是靜態變數只初始化一次,防止在其他檔案中被引用;static區域性變數與普通區域性變數的區別除了值在啟動程式時初始化一次外,就是它的值在程式的整個週期內都存在,兩次函式呼叫期間,它的值保持不變;區域性靜態變數在函式呼叫之間的值保持不變,根據這個特性,可以用於記錄函式呼叫或類建立的一些資訊。

static函式與普通函式的區別是static函式在記憶體中只有乙份,而普通函式在每次被呼叫都維持乙份拷貝。

extern關鍵字用來宣告另乙個檔案中的全域性變數。所以extern和static是矛盾的,不能同時使用。

extern 「c」關鍵字

c++編譯器將extern 「c」中的**單做c語言**處理。extern c大括號所包圍的範圍中,c++的名稱修飾機制不起作用,對於visual c++,直接在變數名和函式名前加」_」。但對於linux下的gcc,extern 「c」後面的符號都是修飾後符號。

:在c語言中不支援使用extern關鍵字

這裡列舉我平時程式設計時遇到的問題及處理方案

在我用vs2012呼叫c語言寫的庫時,出現「error lnk2019: 無法解析的外部符號 clgetplatformids「的錯誤。

原因通常是沒有包含相應的lib,也就是說鏈結器沒搜尋到相應lib中的clgetplatformids目標模組,基於這種情況,我思考會不會是這個函式在標頭檔案中是c語言函式的宣告與定義,但是我又在c++**中包含該標頭檔案,導致其採用c++的名稱修飾機制而無法與c語言庫中符號鏈結。所以對於c++呼叫c庫,需要新增extern 「c」關鍵字宣告。

通常的做法是定義巨集

#ifdef __cplusplus

extern c"

#endif

但是如果這個c原始碼已經編譯成庫,但是模組的標頭檔案中沒有包含extern 「c」,則在c++檔案中,需要新增

extern

"c"

這相當於在cl.h標頭檔案中所有的宣告都新增了extern。

鏈結與const、static、extern——記憶體分配與讀寫

無鏈結性:在**塊中的區域性變數(包括static區域性變數)

外部鏈結:函式之外定義的所有變數(除了const變數)和函式預設為外部鏈結性。在定義時使用extern關鍵字顯式指定識別符號具有外部鏈結。也就是說在多個檔案程式中,可以在檔案並且只能在乙個檔案中定義全域性變數,其他檔案要使用該變數,要在變數前新增extern關鍵字。當有extern時,只是告知編譯器存在這個變數,編譯器並不為該變數分配儲存空間,即真正的宣告;若沒有extern,則在宣告的同時,編譯器也為該變數分配儲存空間。

內部鏈結:全域性static變數和const變數為內部鏈結,為了使const具有外部鏈結以便讓另外乙個檔案可以對它引用,必須在當前檔案裡明確把它定義為extern並初始化。

應使用鏈結性為外部的多檔案程式的不同檔案中共享資料,而使用鏈結性為內部的靜態變數在同一檔案中的多個函式間共享資料

volatile關鍵字

告訴編譯器「該變數不知道何時回改變「,防止編譯器依據變數的穩定性(短期內值不變)作任何優化。

volatile關鍵字與多度優化

在多執行緒環境下,即使合理地使用了鎖,也不一定能保證執行緒安全。

x=y=0

thread1 thread2

x=1 y=1

r1=y r2=x

由於cpu的動態排程或編譯器的優化,執行程式時,有可能交換兩條毫不相干的相鄰指令的順序,導致r1=r2=0的情況的發生。而volatile關鍵字可以試圖阻止優化。

(1)阻止編譯器為了提高速度將乙個變數快取到暫存器而不寫回。也就是說防止編譯器根據變數的穩定性作任何優化,假設要讀乙個硬體中的暫存器,將使用這個關鍵字。無論何時需要volatile變數的值,編譯器都要硬著頭皮頭讀,即使該行之前剛剛讀過。

(2)阻止編譯器調整volatile變數的指令順序。(這一步其實只能阻止編譯器的優化換序,並不能 阻止cpu動態排程換序)

:阻止cpu亂序執行的唯一辦法是呼叫cpu提供barrier指令;

關鍵字restrict

關鍵字restrict只用於限定指標;該關鍵字用於告知編譯器,所有修改該指標所指向內容的操作全部都是基於(base on)該指標的,即不存在其它進行修改操作的途徑;這樣的後果是幫助編譯器進行更好的**優化,生成更有效率的彙編**。

最後注意一點,restrict是c99中定義的關鍵字,c++目前並未引入;在gcc可通過使用引數」 -std=c99」

來開啟對c99的支援

enum列舉型別

本質上,enum是乙個int型,但c++不允許enum到int的隱式轉換。列舉的型別名也是可選的。enumchoice;可以立即定義乙個enum例項。乙個類中的列舉在編譯期間分配值,不占用物件的記憶體空間。但通常優先選擇static const而盡量不是用enum。列舉常量的缺點是:它的隱含資料型別是整數,其最大值有限,且不能表示浮點數

register變數

關鍵字register只是告訴編譯器「盡可能快地訪問該變數」dawn並不能保證將變數放置在暫存器中。同時,register有許多限制,比如不能獲取register變數的位址,不能將其宣告為全域性或靜態變數,因為register變數沒有記憶體位址。因此,最好避免使用。

C語言關鍵字總結

每天進步一點點。若萌新總結有誤,望牛人不吝賜教。要學習c語言關鍵字,首先要知道什麼是c語言關鍵字。簡單的理解,c語言關鍵字就是由c標準規定的 具有特殊用途的單詞。那麼在c語言中都有哪些標準呢,這裡我簡單介紹兩個 看 c和指標 的小夥伴應該會經常看到這兩個 k r c 1978年由 ritchie 和...

C語言關鍵字總結

auto 區域性變數 自動儲存 char 單位元組整型資料 int基本整型資料 long長整型資料 void定義無型別資料 double定義雙精度浮點型資料 float定義單精度浮點型資料 short短整型資料 volatile該變數在程式中執行中可被隱含地改變 unsigned定義無符號資料 si...

const關鍵字總結c

const成員函式只能呼叫const成員函式 const成員函式中不能改變成員變數的值,但是可以訪問所有變數 非const函式可以呼叫const函式 因為非const可能會修改屬性值,所以在const物件情況下,非const方法不能被呼叫,只能呼叫const方法 const函式可被非const過載,...