C++中的long long與__int64
1、long long 和 __int64
在C++ Primer
當(dāng)中提到的64位的int只有long long
,但是在實(shí)際各種各樣的C++編譯器當(dāng)中,64位的int一直有兩種標(biāo)準(zhǔn)。一種是long long
,還有一種是__int64
,非主流的VC甚至還支持_int64。
對(duì)于一般的C++開發(fā)者來說,其實(shí)這個(gè)問題不那么要緊,因?yàn)樵趯?shí)際開發(fā)當(dāng)中,絕大多數(shù)情況使用32位的int就足夠應(yīng)付了。很少會(huì)出現(xiàn)超過int
范圍的情況,但是對(duì)于算法玩家來說,這是一個(gè)必須考量的問題。因?yàn)楹芏囝}目會(huì)故意把范圍弄得很大,考察選手對(duì)于數(shù)據(jù)范圍的敏感。
關(guān)于long long
和__int64
,我們有非常多的問題要討論,我們一個(gè)一個(gè)來說。
2、歷史遺留問題
首先是聊聊這個(gè)問題的背景,為什么會(huì)有兩種標(biāo)準(zhǔn)呢?這并不是C++的標(biāo)準(zhǔn)不嚴(yán)謹(jǐn),或者是各大編譯器亂來,背后是有一個(gè)歷史遺留問題的。
long long
最早是C99標(biāo)準(zhǔn)引進(jìn)的,然而VC6.0推出于1998年,在C99標(biāo)準(zhǔn)之前。所以當(dāng)時(shí)微軟就自己搞出來一個(gè)變量叫做__int64
來表示64位整數(shù)。很多同學(xué)使用的第一個(gè)C++的編譯器就是VC6.0,所以記得在VC6.0當(dāng)中要使用__int64
而非long long。
既然VC6.0搞出了__int64,那么微軟后續(xù)的C++版本顯然就必須要兼容它。所以在win系統(tǒng)當(dāng)中,這個(gè)__int64
的變量類型就一直沿用了下來。當(dāng)然,由于C++標(biāo)準(zhǔn)的更新,當(dāng)然最新的visual studio
已經(jīng)支持long long
了。
GCC并不是基于windows
系統(tǒng)的,自然支持long long
。win平臺(tái)下的一些其他IDE如dev C++
,CodeBlocks
等也支持long long
,因?yàn)樗鼈優(yōu)榱撕臀④浀南到y(tǒng)兼容,所以也支持__int64
。所以一個(gè)比較簡單的區(qū)分方法是,判斷編譯器運(yùn)行的操作系統(tǒng)是否是windows,如果是windows
使用__int64
,否則使用long long
。
3、cin、cout和scanf、printf的選擇問題
這個(gè)問題對(duì)于C++開發(fā)工程師來說同樣不是個(gè)問題,沒有任何選擇的必要,無腦用cin
、cout
就完事了。但對(duì)于算法競賽玩家來說,這依然是一個(gè)要考慮的問題。
因?yàn)樵谒惴ǜ傎惍?dāng)中,尤其是當(dāng)數(shù)據(jù)量很大的時(shí)候,讀入和輸出占據(jù)的時(shí)間是非??捎^的??雌饋碇皇?code>cin cout和scanf
和printf
的差別,但是兩者的性能差異非常大。
我曾經(jīng)做過實(shí)驗(yàn),同樣的數(shù)據(jù),使用scanf
和printf
的效率大約是cin
、cout
的十倍以上。在小數(shù)據(jù)量的時(shí)候當(dāng)然沒有差別,但數(shù)據(jù)量很大的時(shí)候影響非常大。很有可能導(dǎo)致同樣的題目,同樣的算法,別人通過了,但是我們卻超時(shí)了的情況。
關(guān)于性能差異的原因,主要有兩種解釋。一種解釋是說cin
為了與scanf
混用,而不用擔(dān)心指針混亂,加上了綁定,總是會(huì)與stdin
保持同步。正是這一步操作消耗了大量的時(shí)間。同理,cout
也會(huì)有類似的問題。第二種解釋是cout在輸出之前會(huì)把要輸出的內(nèi)容先存入緩存區(qū),中間多了一個(gè)步驟,也會(huì)帶來性能的降低。
關(guān)于cin與stdin同步帶來的開銷,我們是有辦法解決的,只需要在加上這一行代碼:
std::ios::sync_with_stdio(false);
這行代碼的意思是取消cin
、cout
與stdin
、stdout
的指針同步,會(huì)使得cin
、cout
的性能大大提升,達(dá)到和scanf
、printf
相差無幾的程度。當(dāng)然,更好的方法是使用scanf
、printf
代替。
而要使用scanf
和printf
又有一個(gè)問題,它們是C語言的標(biāo)準(zhǔn)輸入輸出方式,需要提供標(biāo)識(shí)符來代表變量的類型,那么問題來了long long
和__int64
的標(biāo)識(shí)符是什么呢?
這個(gè)其實(shí)一查就知道了,long long
的標(biāo)識(shí)符是lld,所以我們使用scanf讀入一個(gè)long long類型的數(shù)寫成:
long long a; scanf("%lld", &a);
__int64的標(biāo)識(shí)符是I64d,注意這里是大寫的i,不是l。
__int64 a; scanf("%I64d", &a);
但是這里面有一個(gè)很大的坑點(diǎn),前面說了,目前在windows
平臺(tái)的編譯器已經(jīng)兼容了long long
類型。但是即便如此,在2013年之前的版本里,我們輸出的時(shí)候還是要使用%I64d,這是因?yàn)槲④浱峁┑膍svcrt.dll庫只支持%I64d的方式。相當(dāng)于從底層上斷絕了使用%lld輸出的可能。2013年微軟修復(fù)了這個(gè)問題,添加了對(duì) %lld 的支持。
所以比較簡單的區(qū)分方法就是看操作系統(tǒng),如果是windows
系統(tǒng),那么一律使用__int64準(zhǔn)沒錯(cuò)。如果是linux或者是Mac系統(tǒng),那么統(tǒng)一使用long long
。
我在網(wǎng)上找到了大神做的總結(jié)表,也可以直接參考下表:
變量定義 | 輸出方式 | gcc(mingw32) | g++(mingw32) | gcc(linux i386) | g++(linux i386) | MicrosoftVisual C++ 6.0 |
---|---|---|---|---|---|---|
long long | “%lld” | 錯(cuò)誤 | 錯(cuò)誤 | 正確 | 正確 | 無法編譯 |
long long | “%I64d” | 正確 | 正確 | 錯(cuò)誤 | 錯(cuò)誤 | 無法編譯 |
__int64 | “l(fā)ld” | 錯(cuò)誤 | 錯(cuò)誤 | 無法編譯 | 無法編譯 | 錯(cuò)誤 |
__int64 | “%I64d” | 正確 | 正確 | 無法編譯 | 無法編譯 | 正確 |
long long | cout | 非C++ | 正確 | 非C++ | 正確 | 無法編譯 |
__int64 | cout | 非C++ | 正確 | 非C++ | 無法編譯 | 無法編譯 |
long long | printint64() | 正確 | 正確 | 正確 | 正確 | 無法編譯 |
到此這篇關(guān)于C++
中的long long
與__int64
的文章就介紹到這了,更多相關(guān)C++ long long __int64
內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
注:文章轉(zhuǎn)自微信公眾號(hào):Coder梁(ID:Coder_LT)
相關(guān)文章
基于C語言實(shí)現(xiàn)的aes256加密算法示例
這篇文章主要介紹了基于C語言實(shí)現(xiàn)的aes256加密算法,結(jié)合具體實(shí)例形式詳細(xì)分析了C語言實(shí)現(xiàn)的aes256加密算法實(shí)現(xiàn)步驟與使用技巧,需要的朋友可以參考下2017-02-02opencv3機(jī)器學(xué)習(xí)之EM算法示例詳解
這篇文章主要介紹了opencv3機(jī)器學(xué)習(xí)之EM算法的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06基于Qt實(shí)現(xiàn)的自定義樹結(jié)構(gòu)容器
在Qt框架中,盡管其提供了許多強(qiáng)大的容器類,但缺少一個(gè)通用的、靈活的樹結(jié)構(gòu)容器,所以本文將設(shè)計(jì)并實(shí)現(xiàn)一個(gè)可復(fù)用的自定義樹結(jié)構(gòu)容器,需要的可以參考下2024-12-12