2016-11-05 265 views

回答

3

它的幫手來計算整數的基於2-數,即它返回最高設定的指標位數(或-1代表0)。

I.e.對於1,它將返回0,對於16,將返回4,對於1024,將返回10,等等。

這可用於有效地預測數組的預分配大小,舍入到最近的2次冪,這樣的事情。

請注意,作爲以__開頭的其他函數,它是編譯器或庫的內部函數,因此您不應該依賴它的存在,因此此代碼不可移植。 std庫的其他實現可以帶有完全解決方案和類似助手的不同名稱(如果他們使用類似的東西)。

POSIX提供了類似的功能 - ffs(),也有ffsl和ffsll(請參閱相同的頁面),這是GNU擴展,分別使用long和long long。

對於評論中的問題 - 如何從Java中使用它。由於上述原因,首先它不是好主意,其次它需要JNI包裝。第三,但最重要的 - 實際上沒有理由。 Java已經提供了類似的方法Integer.heghestOneBit(),雖然註釋它與所描述的std :: __ lg相比返回+1,即0代表0,1代表1代表11代表1024等。

+0

感謝您的回覆!我怎樣才能用這個與JAVA? – tuanptit

+1

你不能這樣做,除非你爲此創建了JNI包裝器(並且這仍然是'std'的內部函數,所以你不應該依賴它的存在)。無論如何,這是沒有意義的,因爲Java提供了相同的:['Integer.highestOneBit'](https://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html#highestOneBit( int))(返回0表示0,1表示1,所以一般移動+1) –

+1

你可能還想指出'std :: __ lg'不是標準C++的一部分。所有以雙下劃線開頭的標識符都是爲實現保留的(這意味着它們可以在標準庫的實現中使用,但不能依賴標準庫的每個實現中的特定標識符)。試圖爲它創建一個JNI包裝將是瘋狂的,除非你很高興你的本地代碼被鎖定到特定的C++編譯器或庫版本。 – Peter

2

它是您的編譯器內部使用的標識符很可能是GCC),因爲的所有標識符都是雙下劃線屬於編譯器實現。

無法在您自己的代碼中看到或使用類似__lg的東西。使用標準庫的接口,而不是它的實現。如果你自己的代碼直接使用__lg,那麼你不能保證代碼將編譯或做任何其他編譯器或甚至與任何其他版本的編譯器正確的東西。

作爲C++標準說在§2.10[lex.name]

包含一個雙下劃線以下劃線後跟大寫字母 __或開始 被保留到 實施用於任何用途的每個標識符。

至於GCC的東西實際上是什麼,只要看看Google搜索「std :: __ lg」的source code

根據實際類型的block_szpos_l,它應該是這樣的:

/// This is a helper function for the sort routines and for random.tcc. 
// Precondition: __n > 0. 
template<typename _Size> 
    inline _Size 
    __lg(_Size __n) 
    { 
    _Size __k; 
    for (__k = 0; __n != 0; __n >>= 1) 
    ++__k; 
    return __k - 1; 
    } 

或者這樣:

inline int 
__lg(int __n) 
{ return sizeof(int) * __CHAR_BIT__ - 1 - __builtin_clz(__n); } 

現在,__CHAR_BIT__像標準CHAR_BIT宏。正如GCC documentation說:

定義到焦炭中的 數據類型的表示中使用的比特數。它的存在是爲了使數字 的標準報頭限制正常工作。你不應該直接使用這個宏;相反,請包含相應的標題。

__builtin_clz是另一個GCC特定功能。再次,GCC documentation解釋其目的:

返回引領X 0位,從最高 顯著位位置的數量。如果x是0,結果是不確定的。

我想如果你需要這樣的功能,那麼你自己寫它是微不足道的。事實上,問題在於你爲什麼首先需要它。真正的問題的答案可能在於int n = std::__lg(block_sz - pos_l + 1);系列的代碼。


事情要記住:

  • 不要在自己的代碼中使用兩個連續下劃線什麼。
  • GCC是開源的,所以特殊功能或宏的內部實現不是祕密,但可以輕鬆在線瀏覽。
相關問題