第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

為什么預處理宏是邪惡的,還有什么可供選擇的?

為什么預處理宏是邪惡的,還有什么可供選擇的?

C++
一只萌萌小番薯 2019-07-02 16:50:53
為什么預處理宏是邪惡的,還有什么可供選擇的?我一直問這個問題,但我從來沒有收到過一個很好的答案,我想幾乎所有程序員在寫第一個“HelloWorld”之前都會遇到“宏不應該被使用”、“宏是邪惡的”等短語,我的問題是:為什么?有了新的C+11,在這么多年之后,還有真正的替代品嗎?簡單的部分是關于宏的,比如#pragma,它們都是特定于平臺的和編譯器特定的,而且大多數(shù)情況下它們都有嚴重的缺陷,例如#pragma once這在至少2種重要情況下是容易出錯的:相同的名稱在不同的路徑以及一些網(wǎng)絡設置和文件系統(tǒng)中。但總的來說,宏和其使用的替代方案又如何呢?
查看完整描述

3 回答

?
有只小跳蛙

TA貢獻1824條經(jīng)驗 獲得超8個贊

宏就像任何其他工具一樣-用于謀殺的錘子不是邪惡的,因為它是錘子。以這種方式使用它是邪惡的。如果你想釘子,錘子是一個完美的工具。

宏有幾個方面使它們變得“糟糕”(稍后我將對每個方面進行詳細討論,并提出備選方案):

  1. 無法調(diào)試宏。
  2. 宏觀擴張會導致奇怪的副作用。
  3. 宏沒有“命名空間”,因此如果宏與其他地方使用的名稱沖突,則會得到不需要的宏替換,這通常會導致奇怪的錯誤消息。
  4. 宏可能會影響你沒有意識到的事情。

讓我們在這里展開一點:

1)宏不能調(diào)試。當您有一個轉換為數(shù)字或字符串的宏時,源代碼將具有宏名稱,并且有許多調(diào)試器,您無法“看到”宏轉換為什么。所以你不知道到底發(fā)生了什么。

更換*使用enumconst T

對于“類似函數(shù)”的宏,因為調(diào)試器工作在“您所在的每個源行”級別上,因此無論是一個語句還是100個語句,宏都將充當單個語句。很難弄清楚到底是怎么回事。

更換:使用函數(shù)-如果需要“快速”,則使用內(nèi)聯(lián)(但請注意,過多的內(nèi)聯(lián)不是一件好事)

2)宏觀擴張會產(chǎn)生奇怪的副作用。

著名的是#define SQUARE(x) ((x) * (x))以及使用x2 = SQUARE(x++)..這導致了x2 = (x++) * (x++);,即使它是有效的代碼[1],幾乎肯定不是程序員想要的。如果它是一個函數(shù),那么做x+就可以了,而x只會增加一次。

另一個例子是宏中的“如果其他”,比如我們有:

#define safe_divide(res, x, y)   if (y != 0) res = x/y;

然后

if (something) safe_divide(b, a, x);else printf("Something is not set...");

它實際上變成了完全錯誤的東西.。

更換*真正的職能。

3)宏沒有命名空間。

如果我們有一個宏:

#define begin() x = 0

我們在C+中有一些使用BEGIN的代碼:

std::vector<int> v;... stuff is loaded into v ... for (std::vector<int>::iterator it = myvector.begin() ; it != myvector.end(); ++it)
   std::cout << ' ' << *it;

現(xiàn)在,您認為您得到了什么錯誤,您在哪里查找錯誤(假設您已經(jīng)完全忘記-或者甚至不知道-其他人編寫的某個頭文件中的開始宏?[更有趣的是,如果您在包含之前包含了這個宏-當您查看代碼本身時,您將陷入完全沒有意義的奇怪錯誤中。

更換好吧,與其說是替換,不如說是“規(guī)則”-只對宏使用大寫名稱,而從不將所有大寫名稱用于其他內(nèi)容。

4)宏有你沒有意識到的效果

承擔這一職能:

#define begin() x = 0#define end() x = 17... a few thousand lines of stuff here ... void dostuff(){
    int x = 7;

    begin();

    ... more code using x ... 

    printf("x=%d\n", x);

    end();}

現(xiàn)在,如果不看宏,您可能會認為BEGIN是一個函數(shù),它不應該影響x。

這類事情,我見過更復雜的例子,真的會把你的一天搞得一團糟!

更換:不要使用宏設置x,也不要將x作為參數(shù)傳入。

有時,使用宏肯定是有益的。一個例子是用宏包裝函數(shù)以傳遞文件/行信息:

#define malloc(x) my_debug_malloc(x, __FILE__, __LINE__)#define free(x)  my_debug_free(x, __FILE__, __LINE__)

現(xiàn)在我們可以用my_debug_malloc作為代碼中的常規(guī)malloc,但是它有額外的參數(shù),所以當它結束時,我們掃描“哪些內(nèi)存元素尚未被釋放”,我們可以打印分配的位置,這樣程序員就可以跟蹤泄漏。

[1]“在順序點”不止一次更新一個變量是未定義的行為。序列點與語句不完全相同,但對于大多數(shù)意圖和目的,這是我們應該考慮的。這樣做x++ * x++將更新x兩次,這是未定義的,可能會導致不同系統(tǒng)上的不同值,以及x也是。


查看完整回答
反對 回復 2019-07-02
?
慕標琳琳

TA貢獻1830條經(jīng)驗 獲得超9個贊

“宏是邪惡的”這句諺語通常指的是#Definition,而不是#實用主義。

具體而言,這一表述指的是以下兩種情況:

  • 將幻數(shù)定義為宏

  • 使用宏替換表達式

隨著新的C+11有一個真正的選擇,經(jīng)過這么多年?

是的,對于上面列表中的項目(神奇的數(shù)字應該用const/conexpr來定義,表達式應該用[Normal/inlineTemplate/inlineTemplate]函數(shù)來定義。

以下是將魔術數(shù)字定義為宏和用宏替換表達式(而不是定義用于計算這些表達式的函數(shù))所帶來的一些問題:

  • 當為魔術數(shù)字定義宏時,編譯器不保留定義值的類型信息。這可能導致編譯警告(和錯誤),并混淆調(diào)試代碼的人員。

  • 當定義宏而不是函數(shù)時,使用該代碼的程序員期望它們像函數(shù)一樣工作,而它們沒有。

考慮以下代碼:

#define max(a, b) ( ((a) > (b)) ? (a) : (b) )int a = 5;int b = 4;int c = max(++a, b);

在分配給c之后,您將期望a和c為6(使用std:max而不是宏)。相反,代碼執(zhí)行:

int c = ( ((++a) ? (b)) ? (++a) : (b) ); // after this, c = a = 7

此外,宏不支持命名空間,這意味著在代碼中定義宏將限制客戶端代碼的名稱。

這意味著,如果您定義了上面的宏(對于max),您將不再能夠#include <algorithm>在下面的任何代碼中,除非您顯式地編寫:

#ifdef max#undef max#endif#include <algorithm>

擁有宏而不是變量/函數(shù)也意味著您無法獲取它們的地址:

  • 如果宏作為常量計算為魔術數(shù)字,則不能按地址傳遞它。

  • 對于宏作為函數(shù),您不能使用它作為謂詞,或接受該函數(shù)的地址或?qū)⑵湟暈楹健?/trans>

編輯:例如,#define max上文:

template<typename T>inline T max(const T& a, const T& b){
    return a > b ? a : b;}

這將執(zhí)行宏所做的一切,但有一個限制:如果參數(shù)的類型不同,模板版本將強制您顯式(這實際上會導致更安全、更顯式的代碼):

int a = 0;double b = 1.;max(a, b);

如果此max被定義為宏,則代碼將編譯(帶有警告)。

如果這個max被定義為一個模板函數(shù),編譯器將指出歧義,您必須說max<int>(a, b)max<double>(a, b)(從而明確說明您的意圖)。


查看完整回答
反對 回復 2019-07-02
?
拉風的咖菲貓

TA貢獻1995條經(jīng)驗 獲得超2個贊

一個常見的問題是:

#define DIV(a,b) a / b

printf("25 / (3+2) = %d", DIV(25,3+2));

它將打印10,而不是5,因為預處理器會這樣擴展它:

printf("25 / (3+2) = %d", 25 / 3 + 2);

這個版本更安全:

#define DIV(a,b) (a) / (b)


查看完整回答
反對 回復 2019-07-02
  • 3 回答
  • 0 關注
  • 276 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網(wǎng)微信公眾號