【问题标题】:Why I have to use %u with unsigned int and I can use %i with unsigned char?为什么我必须将 %u 与 unsigned int 一起使用,而我可以将 %i 与 unsigned char 一起使用?
【发布时间】:2018-12-28 16:24:21
【问题描述】:

我尝试在 C 中使用数据类型。我的第一个问题是 printf() 使用 unsigned int 显示负值。我用 %u 而不是 %i 解决了这个问题。

但是 unsigned char 仍然适用于 %i,这怎么可能?

#include <stdio.h>

int main(void) {
    unsigned int a;
    unsigned char b;

    a = -7;
    b = -1

    printf("a=%u\nb=%i\n", a, b);

    return 0;
}

【问题讨论】:

  • 无论如何,大多数可打印的字符值都低于 127,因此您可能不会看到任何负值。最后一位(值 128 及以上)将编码负值。
  • 而且 %i 的范围(32 位)比一个字节大,所以无论如何你都不会跳过那个符号位。
  • 仅供参考,您可能会发现 this question 很有趣
  • 另一种说法:最好避免未定义的行为!...您能猜出当您使用较大的数据类型和较小的模式时会发生什么,例如,double%f 一起使用(注意: 不适用于scanf())...?

标签: c types


【解决方案1】:

如果你看到例如this printf (and family) reference 你会看到"%i" 格式可以做

有符号整数转换为十进制表示[-]dddd

[强调不是我的]

由于您传递了unsigned int,因此您的格式说明符和值不匹配,导致undefined behavior

此外,对于可变参数函数(例如printf),小于int(例如char,有符号或无符号)的参数是promotedint。同样,由于结果值是 int(已签名)并且您使用 "%u" 格式,因此格式说明符和参数类型之间存在不匹配。

【讨论】:

    【解决方案2】:

    如前所述,对于 unsigned char 类型的变量,使用 'i' 作为格式说明符是不正确的。

    当您不确定任何特定(整数)类型的正确格式时,您可以查看 inttypes.h,其中包含一堆用于可移植格式字符串的宏。根据您开发的平台,正确的格式说明符可能会有所不同(例如,uint16_t 可以是“u”或“hu”,int32_t 可以是“d”或“ld”)。

    您可以将此标头用作“备忘单”,也可以像这样实际编写格式字符串:

    printf("a=%"PRIu32"\nb=%"PRIu8"\n", a, b);
    

    请注意,要使代码真正可移植,您当然还需要使用 uint8_t 代替 unsigned char,并使用 uint32_t 代替 int。

    【讨论】:

      猜你喜欢
      • 2017-08-23
      • 1970-01-01
      • 2015-01-12
      • 2017-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多