C 知識高階之 defines使用優化

2021-10-06 16:34:25 字數 3076 閱讀 1899

在介紹#defines使用優化之前,要首先簡單介紹一下編譯原理:

比如以c語言為例:

1.預處理階段

工作內容:a.巨集替換;b.標頭檔案展開;c.去注釋;d.條件編譯

語言轉換:c語言 ---------> c語言

**2.編譯階段 **

工作內容:檢查語法錯誤

語言轉換:c語言 ---------> 組合語言

3.彙編

語言轉換:組合語言 ---------> 二進位制

4.鏈結

以上只是簡單介紹了一下編譯大概過程,詳細工作原理還要去查詢資料,這裡不做過多說明。

#define 巨集,它在c語言中就已經存在,c++語言中也延用過來,接下來簡單介紹一下他的使用方法和具體的優化。

1.定義:#define 巨集名字 替換物件 (值) (替換物件可為空,比如定義乙個標頭檔案)

2.巨集可以進行函式替換,常量替換,函式替換時可以不帶引數型別

特別說明:巨集引數需要加括號;巨集替換的整體內容需要加括號 ;巨集函式中不可以出現遞迴

#ifndef:指巨集沒有被定義則執行下面的語句,否則不執行 和 #endif 配套使用

移除巨集:

#undef:作用於它被定義後的全部位置,定義之前不作用;如果要重定義巨集,需要先移除巨集,然後再重定義巨集

巨集函式和常規函式的區別:

1.巨集函式的優點:

a.巨集函式比常規函式在程式的規模和執行速度更勝一籌;

b.巨集函式的引數不用定義型別,更類似於c++的模板函式,乙份**可以解決多種型別資料的運算;

(我們知道c++裡面有模板,我們可以使用模板替換,但是c語言沒有模板,所以在c語言中巨集函式的概念類似於c++的模板函式)

2.巨集函式的缺點:

a.巨集函式使**文字增大,呼叫也增大;

b.巨集函式與型別無關;

c.巨集引數的安全性很弱;

巨集還有很多定義的方式,比如條件編譯裡面的巨集,#if … #elif … #endif 等,這裡不再介紹,如果感興趣可以研究下c語言中巨集的使用。

巨集的缺點:

1.定義巨集常量後,我們通過編譯原理知道,在預處理的時候巨集會進行巨集替換,如果在編譯階段出現巨集常量問題,將巨集常量替換成了乙個真正的值,比如定義了乙個巨集常量為20,編譯時出問題了,錯誤會告訴我們是20出問題了,但是不會告訴你是哪個巨集出問題了,那麼如果我們專案很大的話,這個問題查起來就非常麻煩了。

2.定義巨集函式,對於巨集的引數安全處理非常麻煩,要加各種括號還不能保證其安全性;

3.巨集沒有作用域的概念,封裝性太弱,不存在private 巨集的概念。

c++巨集的優化:

1.對於單純的常量,我們最好使用const 或者 enum 替換掉巨集常量;

2.對於形似函式的巨集,我們最好使用 inline函式來替換 巨集函式;

優化分析:

const替換巨集常量:

分為兩種情況:

1.類外定義,通常定義式放在標頭檔案內;

特殊情況:如果是定義常量指標的話,通常 const 要寫兩次

2.類內定義

特殊情況:靜態常亮宣告的時候,對於(ints, chars, bools)這種型別定義的變數,直接使用宣告式賦值,不用再額外在.cpp檔案中去定義,以下是標頭檔案中的宣告;

以下是.cpp檔案中的定義:

但是!!以上情況在某些老的編譯器中不支援,不允許static 成員在宣告的時候獲取初始值,這種情況下,那麼我們也需要將初始值放在定義式裡面去;(以上我的vs版本是2017版本的,所以是可以支援的)

但是如果在老的編譯器中,我們需要宣告乙個有效長度的陣列,但是我們又不能在宣告式裡面給該常量去賦初始值怎麼辦?enum hack 列舉 可以幫助我們解決這個問題。

這裡有個特別的知識點,注意變數的型別

同時enum 可以確保在不同的編譯器(不管好壞)裡面,防止不夠優秀的編譯器導致多餘的記憶體分配。

enum hack是模板元的一想基礎技術。

template inline 函式替換巨集函式:

巨集函式的不安全性,比如:

優化成template inline 函式:

同時彌補了巨集函式不能封裝的缺點,而且可以獲得巨集帶來的效率以及一般函式的所有可預料行為和型別的安全性。

巨集的話外題補充:

細心的人應該會發現,當我們用vs建立乙個類的時候,我們的.h標頭檔案 最上面會預設給乙個 「 # pragma once 」,這個是幹嘛的呢?這個和我們下面這個定義方式的目的是一樣的,主要是為了避免同乙個標頭檔案被包含(include)多次。但是二者也有一些細微的差別,具體可以根據個人情況去查閱資料,這裡不具體介紹。

WIFI之知識高階

1.頻譜劃分 十四個通道2.412 2.484 2.402ghz 2.483ghz 1 工作頻段2.4g 2 範圍2.400 2.4835ghz 83.5m頻寬 3 14個子通道 4 每個22mhz寬度 5 相鄰通道中心間隔5mhz 6 只有1,6,11互不干擾 ssid bssid 1 基本服務集...

C 高階知識整理

容器 迭代器 分配器 演算法 仿函式 配接器。分配器給容器分配記憶體空間,演算法通過迭代器獲取容器中內容,仿函式協助演算法完成各種操作,配接器用來套接適配仿函式。vector 連續儲存容器,動態陣列,在堆上分配空間。底層實現 陣列。兩倍容量增長 插入新元素時,如果超過容量,則會重新分配原有個數的兩倍...

C 高階之 函式

入口函式main main 函式是c 的入口函式,一般情況返回值為int型別 這也是c 標準的要求,所以部分嚴格的編譯器要求main返回值必須為int 和正常函式不同的是,如果main函式沒有顯式出現return,大部分編譯器會預設新增return 0而不是編譯失敗。雖然main函式是入口函式,但並...