2011-10-15 12 views
1

例如,如果此整數爲小於255,比它可以在字節被恢復,如何獲得用宏存儲整數值所需的最少字節數?

,如果它大於255,它需要在免得字節。

如何編寫這樣的BYTES_REQUIRED(i)宏?

+1

爲什麼一個宏?你知道如何使用正常的功能嗎? – Mat

+0

@Mat,實際上我只能想到這個:'if(i <255)return 1;否則if(i> 255 && i <2^16)返回2; ...',這太長了是一個宏。 –

+0

爲什麼你需要一個宏? – Mat

回答

0

如果您使用的是C99編譯器,請將其轉換爲(unsigned long long)。 你也可以(也應該)的結構擴展到8首或16個字節(這是作爲一個練習)

#include <limits.h> 

#define BYTES_REQUIRED(i)       \ 
      !((unsigned long)(i) >>  CHAR_BIT) ? 1 \ 
     : !((unsigned long)(i) >> 2 * CHAR_BIT) ? 2 \ 
     : !((unsigned long)(i) >> 3 * CHAR_BIT) ? 3 \ 
     :           4 
+0

爲什麼我需要將它轉換爲無符號long long如果它是c99編譯器? –

+0

由於'unsigned long long'不被C89識別,並且至少與'unsigned long'一樣大。使用'unsigned long long'不會丟失任何東西(除了C89兼容性)並且可能獲得更大範圍的工作值。 – pmg

0

它使用一個有效的分而治之的方法:如果你不

#define BYTES_REQUIRED(i) (((i) & 0xFFFF0000) ? (((i) & 0xFF000000) ? 4 : 3) : (((i) & 0xFF00) ? 2 : 1)) 

介意消除3個字節奇數的情況下,它有與其匹配任何原始類型,這樣做:

#define BYTES_REQUIRED(i) (((i) & 0xFFFF0000) ? 4 : (((i) & 0xFF00) ? 2 : 1)) 

被警告這些手柄沒有一個負數,因爲它看到的S ign作爲已用空間擴展了1位。這需要另一個條件來解釋(例如,如果是負的,否定的)。

0

您實際上需要計算log2(i)。對於編譯器和宏所支持的最大整數值,並沒有簡單的方法來做到這一點。

選項:

1.Calculate在一個循環中的對數:

// 64+-bit version: 
unsigned long BYTES_REQUIRED(unsigned long long i) 
{ 
    unsigned long bits = 0; 
    while (i) 
    { 
    i >>= 1; 
    bits++; 
    } 
    if (bits == 0) bits = 1; 
    return (bits + 7)/8; // we're assuming that byte=8 bits, but CHAR_BIT may be > 8 
} 

2.使用編譯器的固有功能(有效地,專用CPU指令),如果有的話。對於MSVC++:

// 64-bit version, not available for 32-bit code: 
unsigned long BYTES_REQUIRED(unsigned long long i) 
{ 
    unsigned long index; 
    if (_BitScanReverse64(&index, i) == 0) 
    { 
    index = 1; 
    } 
    return (index + 8)/8; 
} 

// 32-bit version, available for 32 and 64-bit code: 
unsigned long BYTES_REQUIRED(unsigned long i) 
{ 
    unsigned long index; 
    if (_BitScanReverse(&index, i) == 0) 
    { 
    index = 1; 
    } 
    return (index + 8)/8; 
} 

// 64-bit version available for 32 and 64-bit code: 
unsigned long BYTES_REQUIRED(unsigned long long i) 
{ 
    unsigned long index; 
    if (_BitScanReverse(&index, (unsigned long)(i >> 32))) 
    { 
    index += 32; 
    } 
    else if (_BitScanReverse(&index, (unsigned long)i) == 0) 
    { 
    index = 1; 
    } 
    return (index + 8)/8; 
} 

3.使用if?:知道最大支持整數類型的大小...其他人已經描述了這種方法。

+0

解決log-base-2給出的位的準確性,這是不需要的。你正在解決一個更難的問題,然後他問,然後分開額外的精度。 _BitScanReverse可能有些意義,因爲它在某些處理器上速度很快,但他要求在編譯時解決某些問題,所以無論如何性能無關緊要。內在原則使得代碼更加便於攜帶並且無需交換。 – VoidStar

0

不幸的是,你問了一個C宏,因爲這個C++模板化函數可能有幫助(它應該適用於你的編譯器支持的任何整數類型)。

template <typename T> int bytesRequired(T value) { 
    boost::function_requires< boost::IntegerConcept<T> >(); 
    for (int i=0; i<=sizeof(T); i++, value/=256) 
    if (value == 0) return i; 
} 

另一種做法,應該是更快的(因爲它的網點),如果你不只是需要編譯時的評價,是由亞歷克斯提到的bitscan。

相關問題