![](/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.