C++中的long long與__int64
1、long long 和 __int64
在C++ Primer
當中提到的64位的int隻有long long
,但是在實際各種各樣的C++編譯器當中,64位的int一直有兩種標準。一種是long long
,還有一種是__int64
,非主流的VC甚至還支持_int64。
對於一般的C++開發者來說,其實這個問題不那麼要緊,因為在實際開發當中,絕大多數情況使用32位的int就足夠應付瞭。很少會出現超過int
范圍的情況,但是對於算法玩傢來說,這是一個必須考量的問題。因為很多題目會故意把范圍弄得很大,考察選手對於數據范圍的敏感。
關於long long
和__int64
,我們有非常多的問題要討論,我們一個一個來說。
2、歷史遺留問題
首先是聊聊這個問題的背景,為什麼會有兩種標準呢?這並不是C++的標準不嚴謹,或者是各大編譯器亂來,背後是有一個歷史遺留問題的。
long long
最早是C99標準引進的,然而VC6.0推出於1998年,在C99標準之前。所以當時微軟就自己搞出來一個變量叫做__int64
來表示64位整數。很多同學使用的第一個C++的編譯器就是VC6.0,所以記得在VC6.0當中要使用__int64
而非long long。
既然VC6.0搞出瞭__int64,那麼微軟後續的C++版本顯然就必須要兼容它。所以在win系統當中,這個__int64
的變量類型就一直沿用瞭下來。當然,由於C++標準的更新,當然最新的visual studio
已經支持long long
瞭。
GCC並不是基於windows
系統的,自然支持long long
。win平臺下的一些其他IDE如dev C++
,CodeBlocks
等也支持long long
,因為它們為瞭和微軟的系統兼容,所以也支持__int64
。所以一個比較簡單的區分方法是,判斷編譯器運行的操作系統是否是windows,如果是windows
使用__int64
,否則使用long long
。
3、cin、cout和scanf、printf的選擇問題
這個問題對於C++開發工程師來說同樣不是個問題,沒有任何選擇的必要,無腦用cin
、cout
就完事瞭。但對於算法競賽玩傢來說,這依然是一個要考慮的問題。
因為在算法競賽當中,尤其是當數據量很大的時候,讀入和輸出占據的時間是非常可觀的。看起來隻是cin cout
和scanf
和printf
的差別,但是兩者的性能差異非常大。
我曾經做過實驗,同樣的數據,使用scanf
和printf
的效率大約是cin
、cout
的十倍以上。在小數據量的時候當然沒有差別,但數據量很大的時候影響非常大。很有可能導致同樣的題目,同樣的算法,別人通過瞭,但是我們卻超時瞭的情況。
關於性能差異的原因,主要有兩種解釋。一種解釋是說cin
為瞭與scanf
混用,而不用擔心指針混亂,加上瞭綁定,總是會與stdin
保持同步。正是這一步操作消耗瞭大量的時間。同理,cout
也會有類似的問題。第二種解釋是cout在輸出之前會把要輸出的內容先存入緩存區,中間多瞭一個步驟,也會帶來性能的降低。
關於cin與stdin同步帶來的開銷,我們是有辦法解決的,隻需要在加上這一行代碼:
std::ios::sync_with_stdio(false);
這行代碼的意思是取消cin
、cout
與stdin
、stdout
的指針同步,會使得cin
、cout
的性能大大提升,達到和scanf
、printf
相差無幾的程度。當然,更好的方法是使用scanf
、printf
代替。
而要使用scanf
和printf
又有一個問題,它們是C語言的標準輸入輸出方式,需要提供標識符來代表變量的類型,那麼問題來瞭long long
和__int64
的標識符是什麼呢?
這個其實一查就知道瞭,long long
的標識符是lld,所以我們使用scanf讀入一個long long類型的數寫成:
long long a; scanf("%lld", &a);
__int64的標識符是I64d,註意這裡是大寫的i,不是l。
__int64 a; scanf("%I64d", &a);
但是這裡面有一個很大的坑點,前面說瞭,目前在windows
平臺的編譯器已經兼容瞭long long
類型。但是即便如此,在2013年之前的版本裡,我們輸出的時候還是要使用%I64d,這是因為微軟提供的msvcrt.dll庫隻支持%I64d的方式。相當於從底層上斷絕瞭使用%lld輸出的可能。2013年微軟修復瞭這個問題,添加瞭對 %lld 的支持。
所以比較簡單的區分方法就是看操作系統,如果是windows
系統,那麼一律使用__int64準沒錯。如果是linux或者是Mac系統,那麼統一使用long long
。
我在網上找到瞭大神做的總結表,也可以直接參考下表:
變量定義 輸出方式 gcc(mingw32) g++(mingw32) gcc(linux i386) g++(linux i386) MicrosoftVisual C++ 6.0
long long “%lld” 錯誤 錯誤 正確 正確 無法編譯
long long “%I64d” 正確 正確 錯誤 錯誤 無法編譯
__int64 “lld” 錯誤 錯誤 無法編譯 無法編譯 錯誤
__int64 “%I64d” 正確 正確 無法編譯 無法編譯 正確
long long cout 非C++ 正確 非C++ 正確 無法編譯
__int64 cout 非C++ 正確 非C++ 無法編譯 無法編譯
long long printint64() 正確 正確 正確 正確 無法編譯
到此這篇關於C++中的long long與__int64的文章就介紹到這瞭,更多相關C++ long long __int64內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- MinGW-w64 C/C++編譯器下載和安裝的方法步驟(入門教程)
- 使用 Visual Studio 2022 開發 Linux C++ 應用程序的過程詳解
- C語言通過gets和gets_s分別實現讀取含空格的字符串
- 在Visual Studio Code中配置C++編譯環境的問題
- redis debug環境搭建過程詳解(使用clion)