简体   繁体   English

将2个uint16_t合并为1个uint32_t

[英]Combining 2 uint16_t into into 1 uint32_t

I have 2 uint16_t's that i want to combine into 1 32 bit number: 我有2个uint16_t,我想组合成1个32位数字:

uint16_t var1 = 255; // 0000 0000 1111 1111
uint16_t var2 = 255; // 0000 0000 1111 1111

uint32_t var3 = (var1 << 16) +  var2;

I expect var3 to be 0000 0000 1111 1111 0000 0000 1111 1111... so 16711935 in decimal but i get 255 ( 0000 0000 0000 0000 0000 0000 1111 1111). 我希望var3为0000 0000 1111 1111 0000 0000 1111 1111 ...所以十进制16711935但我得到255(0000 0000 0000 0000 0000 0000 1111 1111)。

Any ideas? 有任何想法吗?

Thanks 谢谢

When an integer type is being shifted, both operands are promoted first and the resulting integer has the same type of the promoted left operand. 当对整数类型进行移位时,两个操作数都将首先提升,并且所得整数与提升后的左操作数具有相同的类型。

Compiler will first try to promote uint16_t to int and if an int can't hold the value (ie the value is larger than INT_MAX) it will be promoted to unsigned int . 编译器将首先尝试将uint16_t提升为int ,如果一个int无法保存该值(即,该值大于INT_MAX),它将被提升为unsigned int Now if your system uses 16-bit int s the result will still be 16 bits and hence your most significant bits in the case of a left shift will be lost as long as your shift value is less than 16, from which point the behavior is undefined by standard. 现在,如果您的系统使用16-bit int ,结果仍将是16位,因此只要您的shift值小于16,就将丢失左移情况下的最高有效位。未按标准定义。

In that kind of a system, you need to first cast to a wider integer type like uint32_t or uint64_t and then left shift. 在这种系统中,您需要首先转换为更宽泛的整数类型(例如uint32_tuint64_t ,然后左移。 And to be on the safe side, we can always cast the left operand of a shift to the expected type so that our code is not affected by implementation decisions made by compiler designer such as bit widths. 为了安全起见,我们总是可以将移位的左操作数强制转换为期望的type以使我们的代码不受编译器设计者做出的实现决定(如位宽)的影响。

To some extent, this is platform-dependent. 在某种程度上,这取决于平台。 On my nearest system, we get the expected results, which can be demonstrated with a short program: 在我最近的系统上,我们得到了预期的结果,可以通过一个简短的程序进行演示:

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

int main()
{
    uint16_t var1 = 255; // 0000 0000 1111 1111
    uint16_t var2 = 255; // 0000 0000 1111 1111

    uint32_t var3 = (var1 << 16) +  var2;

    printf("%#"PRIx32"\n", var3);
}

Output is 0xff00ff . 输出为0xff00ff

However, your var1 and var2 undergo the normal integer promotions before any arithmetic. 但是,您的var1var2在进行任何算术运算之前都会经过普通的整数提升 If the promoted types can't hold the intermediate result, part of the calculation can be lost, as you see. 如您所见,如果提升的类型不能保存中间结果,则部分计算可能会丢失。

You can avoid the problem by explicitly widening var1 before the arithmetic: 您可以通过在算法前显式扩展var1来避免此问题:

    uint32_t var3 = ((uint32_t)var1 << 16) +  var2;

The equivalent failing program on my system is: 我的系统上等效的失败程序是:

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

int main()
{
    uint16_t var1 = 255; // 00ff
    uint16_t var2 = 255; // 00ff

    uint64_t var3 = ((uint64_t)var1 << 32) +  var2;

    printf("%#"PRIx64"\n", var3);
}

This produces 0x1fe instead of 0xff000000ff if I don't widen var1 with the cast as shown (because on this system, <<32 happens to be a no-op with 32-bit unsigned types). 如果我不按所示使用演员0x1fe0x1fe var1 ,那么它将产生0x1fe而不是0xff000000ff (因为在此系统上, <<32恰好是具有32位无符号类型的无操作)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM