如何从一个long long int中提取出四个unsigned short int?

5
假设我有一个长长的整数,并且想要将其位数构建成四个无符号短整数。这里特定的顺序并不重要。
我通常知道需要移位和截断到无符号短整数的大小。但我认为我可能会在某个地方犯一些奇怪的错误,所以我来问一下。
3个回答

12
#include <stdint.h>
#include <stdio.h>

union ui64 {
    uint64_t one;
    uint16_t four[4];
};

int
main()
{
    union ui64 number = {0x123456789abcdef0};
    printf("%x %x %x %x\n", number.four[0], number.four[1],
                            number.four[2], number.four[3]);
    return 0;
}

这会受到小/大端的影响吗? - slashmais
是的,大端序系统和小端序系统会得到不同的结果。 - C. K. Young
这绝对是一种快速而粗糙的解决方案,与Perl中的“@numbers = unpack 'S4',pack 'Q',$number;”同级。 - C. K. Young
在像Cray和TI DSP这些CPU上,short类型可能是32位的,所以代码很容易失败。 - MSalters
我完全同意这个解决方案根本不可移植。也许我应该修改答案,使用inttypes.h。 :-) - C. K. Young

3
(unsigned short)((((unsigned long long int)value)>>(x))&(0xFFFF))

其中value是您的long long int,而x为四个短整数中的0、16、32或48。


@SteveJessop:我想知道标准中为什么没有规定负数右移或将大值强制转换为未调整大小的有符号类型的行为要求。据我所知,实现可以指定对于所有负数x,“x>>y”将产生42,或将产生y,或以实现作者喜欢的任何无副作用方式计算数字,使得在严格符合规范的代码中,使用负x的“x>>y”基本上是无用的,即使这样的代码也可以同样满意... - supercat
任何“基本正常”的实现可能使用的评估手段。 - supercat
@supercat:我认为这是因为他们不想阻止实现只使用架构的移位操作码,而且由于某种原因,他们不确定能否提供包括所有“远程正常”当前和未来架构的选项列表。目前的情况是,那些严格符合规范的程序需要在移位之前检查整数是否为负数,除非程序员知道它是非负数。在任何移位操作码未产生符合规范行为的架构上,编译器都必须发出代码以检查所有移位操作。 - Steve Jessop
...零填充语义是适当的。我同意,按照现有标准,希望执行符号扩展右移的代码必须跳过一些障碍才能实现。我的问题是,将标准写成这样是否有任何有用的目的。在我看来,如果90%以上的编译器允许以比任何严格符合规范的写法更清晰的方式编写操作(在某些编译器上可能也更有效),那么标准应该承认这一点作为规范,并定义一个宏指示... - supercat
...无论编译器是否遵循这种惯例,都可以为符合特定规范惯例的所有编译器工作的程序定义与合规性相关的术语,即使它们不能在所有编译器上运行。例如,“当使用符合第二类整数语义、第三类指针语义和32位或更大int大小的规范标准的编译器时,程序X严格遵守。”但可惜的是,事情正在朝相反的方向发展;编译器编写人员对支持那些在1989年至2009年间的99%编译器上运行的结构并不感兴趣。 - supercat
显示剩余12条评论

2
union LongLongIntToThreeUnsignedShorts {
   long long int long_long_int;
   unsigned short int short_ints[sizeof(long long int) / sizeof(short int)];
};

那应该可以做到你所想的,而不必玩弄位移操作。

你可以保证结构体中短整型之间不会有填充吗? - Alexander
抱歉 - 我最初写了大约三个无符号整数。这可能会误导你。对此我很抱歉。不过你的回答还是有帮助的。 - Paweł Hajdan
它最初是<code>unsigned short int</code>(可能每个2个字节--没关系)。我的观点是,除非您确定填充/对齐规则,否则该结构是危险的。 - Alexander

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接