日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

宏比较值,坑的一B

發(fā)布時(shí)間:2023/12/20 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 宏比较值,坑的一B 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

昨晚上,我準(zhǔn)備睡覺(jué),連總給我發(fā)了一段代碼

#include?"stdio.h"#define?MAX_MACRO(a,?b)?((a)?>?(b)???(a)?:?(b)) int?MAX_FUNC(int?a,?int?b)?{return?((a)?>?(b)???(a)?:?(b)); }int?main() {unsigned?int?a?=?1;int?b?=?-1;printf("MACRO:?max?of?a?and?b?is:?%d\n",?MAX_MACRO(++a,b));printf("FUNC?:?max?of?a?and?b?is:?%d\n",?MAX_FUNC(a,?b));return?0; }

剛開(kāi)始我是懵得一逼,我覺(jué)得應(yīng)該有坑,就沒(méi)有回答,連總也說(shuō)了,這個(gè)問(wèn)題肯定有坑,原話(huà)是「沒(méi)有坑我就不發(fā)給你了」,既然有坑,我就沒(méi)有繼續(xù)看下去,我怕掉下去后起不來(lái),覺(jué)都沒(méi)得睡了。

然后今天我繼續(xù)搞了下這個(gè)代碼

執(zhí)行結(jié)果如下

MACRO:?max?of?a?and?b?is:?-1 FUNC?:?max?of?a?and?b?is:?2-------------------------------- Process?exited?after?0.03527?seconds?with?return?value?0 請(qǐng)按任意鍵繼續(xù).?.?.

我百思不得姐,遂上網(wǎng)查了下,得到的結(jié)果如下

http://www.myexception.cn/c/324054.html

------解決方案--------------------?

因?yàn)閍是unsigned,比較時(shí)b會(huì)轉(zhuǎn)成unsigned,(unsigned)-1是最大的?

------解決方案--------------------

1.在包含兩種數(shù)據(jù)類(lèi)型的任何運(yùn)算里,兩個(gè)值都被轉(zhuǎn)換成兩種類(lèi)型里面的較高級(jí)別。

2.類(lèi)型級(jí)別從高到低的順序是long double, double, float, unsigned long long, long long, long, unsigned int 和 int.

基于這樣的解釋,我把上面的代碼修改成這樣

#include?"stdio.h"#define?MAX_MACRO(a,?b)?((a)?>?(b)???(a)?:?(b)) int?MAX_FUNC(int?a,?int?b)?{return?((a)?>?(b)???(a)?:?(b)); }int?main() {unsigned?int?a?=?1;long?b?=?-1;printf("MACRO:?max?of?a?and?b?is:?%d\n",?MAX_MACRO(++a,b));printf("FUNC?:?max?of?a?and?b?is:?%d\n",?MAX_FUNC(a,?b));return?0; }

我把 int 修改成了 long,因?yàn)閘ong在unsigned int的前面,如果上面的解釋正確,那么應(yīng)該輸出的是1。

實(shí)際輸出如下:

MACRO:?max?of?a?and?b?is:?-1 FUNC?:?max?of?a?and?b?is:?2-------------------------------- Process?exited?after?0.03618?seconds?with?return?value?0 請(qǐng)按任意鍵繼續(xù).?.?.

所以上面的解釋不正確

針對(duì)這個(gè)問(wèn)題,我們?cè)谌豪镉懻摿撕芫?#xff0c;得出了結(jié)論只能是?這是未定義行為

未定義行為 就是編譯器想怎么就怎么搞,但是寫(xiě)這個(gè)代碼的人,肯定也是有問(wèn)題的,因?yàn)檫@個(gè)代碼是可以?xún)?yōu)化的。

還有一種情況,我們把代碼修改成下面這個(gè)樣子

#include?"stdio.h"#define?MAX_MACRO(a,?b)?((a)?>?(b)???(a)?:?(b)) int?MAX_FUNC(int?a,?int?b)?{return?((a)?>?(b)???(a)?:?(b)); }int?main() {unsigned?char?a?=?1;long?b?=?-1;printf("MACRO:?max?of?a?and?b?is:?%d\n",?MAX_MACRO(++a,b));printf("FUNC?:?max?of?a?and?b?is:?%d\n",?MAX_FUNC(a,?b));return?0; }

這時(shí)候代碼的輸出,大家可以先思考一下

思考后,,,,,,,,,

代碼輸出如下

MACRO:?max?of?a?and?b?is:?3 FUNC?:?max?of?a?and?b?is:?3-------------------------------- Process?exited?after?0.03109?seconds?with?return?value?0 請(qǐng)按任意鍵繼續(xù).?.?.

原因是,宏替換后,++a 被替換了3次

MAX_MACRO(++a,b)((++a)?>?(b)???(++a)?:?(b))

上面扯了那么多,主要是想說(shuō)兩個(gè)事情

1、宏獲取最大值的代碼,這么寫(xiě)容易出現(xiàn)問(wèn)題。

2、知道了問(wèn)題,我們就需要知道如何寫(xiě)是正確的,用函數(shù)的方式就是一種正確的方式

當(dāng)然,不僅是我們的代碼是這樣寫(xiě)的,我看到內(nèi)核代碼里面也這樣寫(xiě)

weiqifa@bsp-ubuntu1804:~$?head?-n?2?/usr/include/sys/param.h /*?Compatibility?header?for?old-style?Unix?parameters?and?limits.Copyright?(C)?1995-2018?Free?Software?Foundation,?Inc. weiqifa@bsp-ubuntu1804:~$?egrep?'MIN\(|MAX\('?/usr/include/sys/param.h? #define?MIN(a,b)?(((a)<(b))?(a):(b)) #define?MAX(a,b)?(((a)>(b))?(a):(b)) weiqifa@bsp-ubuntu1804:~$?uname?-sr Linux?4.15.0-117-generic weiqifa@bsp-ubuntu1804:~$?

既然這個(gè)宏不安全,還這樣寫(xiě)出來(lái),只能說(shuō)有一種可能,寫(xiě)的人希望用這個(gè)函數(shù)的人比較專(zhuān)業(yè)

— — 網(wǎng)上也給出了一個(gè)比較專(zhuān)業(yè)的寫(xiě)法

?#define?max(a,b)?\({?__typeof__?(a)?_a?=?(a);?\__typeof__?(b)?_b?=?(b);?\_a?>?_b???_a?:?_b;?})

__typedef__ 這個(gè)關(guān)鍵字也有點(diǎn)雞肋,懂的人比較少,之前分析一個(gè)內(nèi)核函數(shù)的時(shí)候解釋過(guò)。

—— 測(cè)試代碼

#include?"stdio.h"int?main(void) {int?a?=?100;__typeof__(a)?b?=?-20;printf("%d?%d\n",sizeof(b),b);return?(0); }

程序輸出

4?-20-------------------------------- Process?exited?after?0.03424?seconds?with?return?value?0 請(qǐng)按任意鍵繼續(xù).?.?.

好,既然我們知道了 typedef 這個(gè)好東西,我們?cè)傩薷囊粋€(gè)測(cè)試程序

#include?"stdio.h"#define?MAX_MACRO(a,?b)?((a)?>?(b)???(a)?:?(b)) int?MAX_FUNC(int?a,?int?b)?{return?((a)?>?(b)???(a)?:?(b)); } #define?max(a,b)?\ ({?__typeof__?(a)?_a?=?(a);?\__typeof__?(b)?_b?=?(b);?\_a?>?_b???_a?:?_b;?})int?main() {unsigned?char?a?=?1;long?b?=?-1;printf("MACRO:?max?of?a?and?b?is:?%d\n",?max(++a,b));printf("FUNC?:?max?of?a?and?b?is:?%d\n",?MAX_FUNC(a,?b));return?0; }

這個(gè)代碼也是有坑的,不小心的人可能又掉坑里了。

程序輸出

MACRO:?max?of?a?and?b?is:?2 FUNC?:?max?of?a?and?b?is:?2-------------------------------- Process?exited?after?0.03569?seconds?with?return?value?0 請(qǐng)按任意鍵繼續(xù).?.?.

把 __typeof__ 修改成 typeof 再試一次

#include?"stdio.h"#define?MAX_MACRO(a,?b)?((a)?>?(b)???(a)?:?(b)) int?MAX_FUNC(int?a,?int?b)?{return?((a)?>?(b)???(a)?:?(b)); } #define?max(a,b)?\ ({?typeof?(a)?_a?=?(a);?\typeof?(b)?_b?=?(b);?\_a?>?_b???_a?:?_b;?})int?main() {unsigned?char?a?=?1;long?b?=?-1;printf("MACRO:?max?of?a?and?b?is:?%d\n",?max(++a,b));printf("FUNC?:?max?of?a?and?b?is:?%d\n",?MAX_FUNC(a,?b));return?0; }

程序輸出

MACRO:?max?of?a?and?b?is:?2 FUNC?:?max?of?a?and?b?is:?2-------------------------------- Process?exited?after?0.02998?seconds?with?return?value?0 請(qǐng)按任意鍵繼續(xù).?.?.

可以看到,結(jié)果和上面的一樣

— — 再看一個(gè)修改方案

除了上面的修改方案外,還有另外一種修改方案

代碼如下

#include?<stdio.h>#define?GENERIC_MAX(x,?y)?((x)?>?(y)???(x)?:?(y))#define?ENSURE_int(i)???_Generic((i),?int:???(i)) #define?ENSURE_float(f)?_Generic((f),?float:?(f))#define?MAX(type,?x,?y)?\(type)GENERIC_MAX(ENSURE_##type(x),?ENSURE_##type(y))int?main() {int?a?=?3;int?b?=?5;printf("%d\n",MAX(int,a,b));return?0; }

程序輸出

5-------------------------------- Process?exited?after?0.02871?seconds?with?return?value?0 請(qǐng)按任意鍵繼續(xù).?.?.

這種做法很明顯,就是指定需要比較的類(lèi)型,可以通過(guò)這個(gè)方法規(guī)避因?yàn)轭?lèi)型的問(wèn)題引入錯(cuò)誤。

— — C++ 的模板函數(shù)可以解決這個(gè)問(wèn)題

模板函數(shù)出現(xiàn)后,這類(lèi)問(wèn)題就顯得太簡(jiǎn)單了

#include?<iostream> #include?<string>using?namespace?std;template?<typename?T> inline?T?const&?Max?(T?const&?a,?T?const&?b)? {?return?a?<?b???b:a;? }template?<typename?T> inline?T?const&?Min?(T?const&?a,?T?const&?b)? {?return?b?<?a???b:a;? }int?main?() {int?i?=?2;int?j?=?-1;cout?<<?"Max(i,?j):?"?<<?Max(i,?j)?<<?endl;?cout?<<?"Min(i,?j):?"?<<?Min(i,?j)?<<?endl;?double?f1?=?13.5;?double?f2?=?20.7;?cout?<<?"Max(f1,?f2):?"?<<?Max(f1,?f2)?<<?endl;cout?<<?"Min(f1,?f2):?"?<<?Min(f1,?f2)?<<?endl;?string?s1?=?"Hello";?string?s2?=?"World";?cout?<<?"Max(s1,?s2):?"?<<?Max(s1,?s2)?<<?endl;?cout?<<?"Min(s1,?s2):?"?<<?Min(s1,?s2)?<<?endl;return?0; }

程序輸出

Max(i,?j):?2 Min(i,?j):?-1 Max(f1,?f2):?20.7 Min(f1,?f2):?13.5 Max(s1,?s2):?World Min(s1,?s2):?Hello-------------------------------- Process?exited?after?0.1118?seconds?with?return?value?0 請(qǐng)按任意鍵繼續(xù).?.?.

最后說(shuō)一句,相同的東西比較才有意義,不同的東西,比較沒(méi)有多大意思。

函數(shù)模板,如果理解的不深刻,可以看看書(shū)籍

推薦閱讀:

專(zhuān)輯|Linux文章匯總

專(zhuān)輯|程序人生

專(zhuān)輯|C語(yǔ)言

我的知識(shí)小密圈

總結(jié)

以上是生活随笔為你收集整理的宏比较值,坑的一B的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。