我前幾天在查看散列函數,發現有一個例子的網站。大部分代碼很容易掌握,但是這個宏觀功能我不能真正包裹我的頭。散列函數中的get16bits宏
有人可以分解這裏發生了什麼?
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) +(uint32_t)(((const uint8_t *)(d))[0]))
我前幾天在查看散列函數,發現有一個例子的網站。大部分代碼很容易掌握,但是這個宏觀功能我不能真正包裹我的頭。散列函數中的get16bits宏
有人可以分解這裏發生了什麼?
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) +(uint32_t)(((const uint8_t *)(d))[0]))
基本上它得到32位整數d
的低16位可以把它分解
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) +(uint32_t)(((const uint8_t *)(d))[0]))
uint32_t a = 0x12345678;
uint16_t b = get16bits(&a); // b == 0x00005678
首先我們必須通過一個地址到get16bits()
或它不會工作。
(((uint32_t)(const uint8_t *)(d))[1])) << 8
這首先將32位整數轉換爲8位整數數組並檢索2。 它然後由8位移位的值,因此,並將該低8位到它
+ (uint32_t)(((const uint8_t *)(d))[0]))
在我們的例子這將是
uint8_t tmp[4] = (uint8_t *)&a;
uint32_t result;
result = tmp[1] << 8; // 0x00005600
result += tmp[0]; //tmp[0] == 0x78
// result is now 0x00005678
宏是或多或少當量:
static uint32_t get16bits(SOMETYPE *d)
{
unsigned char temp[ sizeof *d];
uint32_t val;
memcpy(temp, d, sizeof *d);
val = (temp[0] << 8)
+ temp[1];
return val;
}
,但宏參數沒有類型和函數參數一樣。
另一種方法是實際投:
static uint32_t get16bits(SOMETYPE *d)
{
unsigned char *cp = (unsigned char*) d;
uint32_t val;
val = (cp[0] << 8)
+ cp[1];
return val;
}
,這也說明了弱點:通過用1索引,代碼假定的sizeof(* d)爲至少2。
那麼,宏參數'D'被視爲char數組,第一個和零個字符組合成一個16位整數。 – wildplasser
是的,這個宏把'd'指向little-endian的內存(可能是因爲它假設內存包含little-endian數據,即使系統本身可能是big-endian)。 –