【问题标题】:uint32_t is having a negative value when MSB is 1MSB 为 1 时 uint32_t 为负值
【发布时间】:2021-11-25 21:26:28
【问题描述】:

我需要将有符号值转换为无符号值,在尝试使其工作时,我发现 uint32_t 在我将 MSB 分配给 1 时以某种方式被签名。

在这段代码中,我说明了我的意思。 Test1/2 将证明这不仅是 printf 问题,也是算术问题。

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

     void main() {
        int reg1S = 0xfffffff4;
        int reg2S = 0xfffffff2;
              
        uint32_t reg1U = 0xfffffff4;
        uint32_t reg2U = 0xfffffff2;

        uint8_t test1,test2;

        test1 = (reg1S < reg2S ? 1:0);                      
        test2 = (reg1U < reg2U ? 1:0); 

        printf("signed = %d \t",test1);
        printf("unsigned = %d \n", test2);
        printf("reg1S= %d \t", reg1S);
        printf("reg1U= %d \n", reg1U);
        printf("reg2S= %d \t", reg2S);
        printf("reg2U= %d \n", reg2U);
     }

这是代码输出的内容

signed = 0  unsigned = 0 
reg1S= -12  reg1U= -12 
reg2S= -14  reg2U= -14

注意:它不会对 8 位或 16 位无符号整数执行此操作,只有 32 位和 64 位

【问题讨论】:

  • 您为uint32_t 使用了错误的格式说明符。见stackoverflow.com/questions/3168275/…
  • printf() 不知道也不关心传递给它的数据(或者即使没有传递)。如果你告诉它%d,那么无论传递什么,它都会查看它期望数据的位置并将其解释为int 类型。如果传递了浮点变量,则与普通函数不同,没有类型转换(除了类型提升),printf() 再次查看 32 位数据并假定它是int 数据。

标签: c unsigned-integer


【解决方案1】:

%d 用于打印签名类型。要打印无符号类型,请使用%u

此外,小于int 的类型在传递给printf 时将被提升为该类型,这就是您在这些类型中看不到这种行为的原因。

【讨论】:

  • 可能存在unsigned int 小于uint32_t 的病态情况。那么这将不起作用。有一个“正确的”格式说明符"%"PRIu32
  • 感谢这解释了 printf 问题。但它没有解释为什么它说 ffffff4 低于 fffffff2
  • 因为-14 小于-12
  • @MagnusMikkelsen 0xfffffff4 未签名,不适合已签名的 int。因此它正在使用实现定义的结果进行转换(根据port70.net/~nsz/c/c11/n1570.html#6.3.1.3p3)。在您的情况下,它很可能将位模式解释为 2 的补码表示负数。
  • test2 使用无符号整数,因此应该返回 1,因为 0xfffffff4 高于 fffffff2
【解决方案2】:

使用correct formats for fixed size integers

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

 void main() {
    int32_t reg1S = 0xfffffff4; \\ <- implementation defined
    int32_t reg2S = 0xfffffff2; \\ <- implementation defined
          
    uint32_t reg1U = 0xfffffff4;
    uint32_t reg2U = 0xfffffff2;

    printf("reg1S= %"PRIi32" \t", reg1S);
    printf("reg1U= %"PRIu32" \n", reg1U);
    printf("reg2S= %"PRIi32" \t", reg2S);
    printf("reg2U= %"PRIu32" \n", reg2U);
 }

【讨论】:

    猜你喜欢
    • 2020-04-26
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-30
    • 1970-01-01
    相关资源
    最近更新 更多