![](/img/trans.png)
[英]To Write a C Program to take 32 bit integer and display Higher and lower words (16-bits) using union
[英]Returning 16-bits given a pointer in C
一個塊由一個 64 位長的 integer 表示,它被分成 4 個 16 位的部分。
我需要使用下面的 function 返回一個 16 位部分。
unsigned short get_16bitsection(unsigned long *start, int index) {
// Fill this in
}
使用強制轉換來實現這一點很誘人,但一個常見的誤解是“一切都只是字節”,因此您可以安全地做到這一點。 一個稱為嚴格別名的規則實際上禁止這樣做。 您的代碼可能看起來可以工作,特別是在較舊和不太復雜的編譯器上,但在重度優化時代,您違反了這樣的語言規則,實際上是在玩火。
相反,您應該將所需的字節復制到uint16_t
中,然后返回它:
uint16_t get_16bitsection(uint64_t *start, int index) {
uint16_t result;
memcpy(&result, (char*)start + index*sizeof(uint16_t), sizeof(uint16_t));
return result;
}
在這里,我轉換為char*
以便我們可以按字節導航您的塊(此別名是通常嚴格別名規則的特別允許的例外),然后應用index*sizeof(uint16_t)
的偏移量以達到所需的索引(假設您已指定小端序)。 最后,我們將字節復制到result
中,並返回它。
如果您擔心性能,請不要擔心。 您已經將uint16_t
從本地 scope 復制到調用 scope 中; 剛才它有了名字。 如果這個 function比混疊違規版本慢,那么這證明你已經混淆了優化器走得太遠。
只需使用工會。
long int x=0x123456789abcdef0;
union {
long int x;
unsigned short arr[4];
} c;
c.x = x;
printf("%04x %04x %04x %04x\n", c.arr[0], c.arr[1], c.arr[2], c.arr[3]);
結果:
def0 9abc 5678 1234
給定指針返回 16 位
一個塊由一個 64 位長的 integer 表示,它分為 4 個 16 位段
要以獨立於字節序的可移植方式訪問數據並檢索 0:LS 16 位到 3:MS 16 位,請使用>>
。
由於unsigned long
可能只有 32 位,建議使用unsigned long long
或uint_least64_t
。
考慮使指針const
以允許此 function 用於const
數據。
unsigned short get_16bitsection(const unsigned long long *start, int index) {
#define MASK_16BIT 0xFFFFu
return MASK_16BIT & (*start >> (16*index));
}
unsigned short
不是 16 位的稀有機器上很有用。 IAC,我更喜歡面具而不是演員 - 減少范圍的更溫和的方式。(unsigned short)
或(uint16_t)
雖然這稍微不那么可移植,因為uint16_t
可能不存在並且unsigned short
可能 > 16 位。也許我在這里錯過了重點,但它可能就像這樣簡單:
unsigned short get_16bitsection_be(unsigned long *start, int index) {
unsigned short *p = (unsigned short*) start;
return p[3 - index];
}
unsigned short get_16bitsection_le(unsigned long *start, int index) {
unsigned short *p = (unsigned short*) start;
return p[index];
}
大端和小端之間的區別在這里是相關的。
請注意,您應該考慮使用stdint.h
為這些類型賦予更有意義的名稱,並明確您實際在做什么:
uint16_t get_16bitsection_le(uint64_t *start, int index) {
uint16_t *p = (uint16_t*) start;
return p[index];
}
uint16_t get_16bitsection_be(uint64_t *start, int index) {
uint16_t *p = (uint16_t*) start;
return p[3 - index];
}
您的第二種方法走在了正確的軌道上,但是該代碼被許多無關緊要的東西弄得一團糟,再加上沒有意義的* 8
偏移量。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.