【问题标题】:Unintended unsigned max result意外的无符号最大结果
【发布时间】:2014-07-14 18:12:16
【问题描述】:

我正在尝试做 K&R C 的练习 2-1,但是当我运行程序时,结果是这样的:

        UNSIGNED TYPES
UNSIGNED CHAR:  0     255
UNSIGNED SHORT: 0     65535
UNSIGNED INT:   0     -1
UNSIGNED LONG;  0     -1

UNSIGNED INTUNSIGNED LONG 的结果不应该是-1,它应该是引用中的值。 (附录 B.11 第 213 页)

/* UNSIGNED TYPES */
printf("\n\tUNSIGNED TYPES\n");
printf("UNSIGNED CHAR:  %d      %d\n", 0, UCHAR_MAX);
printf("UNSIGNED SHORT: %d      %d\n", 0, USHRT_MAX);
printf("UNSIGNED INT:   %d      %d\n", 0, UINT_MAX);
printf("UNSIGNED LONG:  %d      %d\n", 0, ULONG_MAX);

奇怪的是我不认为我的代码有问题,最小范围是0,因为我读到unsigned 类型是非负数。我已经包含了limits.hfloat.h

我该如何解决这个问题?

完整程序的链接是here

更新 1: 我尝试将 %d 替换为 unsigned long 的最大范围,这似乎可行,但 unsigned int4294967925 而不是 65535。感谢您帮助我解决 unsigned long 问题,我希望你们能帮助我解决 unsigned int 问题。

更新 2: 我将 ULONG_MAX 的字符序列从 %ul 更改为 %lu

这是代码和结果:

代码:

/* UNSIGNED TYPES */
printf("\n\tUNSIGNED TYPES\n");
printf("UNSIGNED CHAR:  %d      %u\n", 0, UCHAR_MAX);
printf("UNSIGNED SHORT: %d      %u\n", 0, USHRT_MAX);
printf("UNSIGNED INT:   %d      %u\n", 0, UINT_MAX);
printf("UNSIGNED LONG:  %d      %lu\n", 0, ULONG_MAX);

结果:

        UNSIGNED TYPES
UNSIGNED CHAR:  0     255
UNSIGNED SHORT: 0     65535
UNSIGNED INT:   0     4294967925
UNSIGNED LONG;  0     4294967925

【问题讨论】:

  • %ul 应该是%lu,而您在结果的最后一行将l 错误转录为1
  • 我已经这样做了,它似乎比%ul 工作得更好,但是你愿意解释一下(如果你知道的话)为什么%ulULONG_MAX 的末尾添加一个吗?为什么%lu 没有?
  • %ul%u 后跟字母 l

标签: c types range unsigned format-specifiers


【解决方案1】:

您需要使用%u 的格式规范来打印无符号整数。

通过使用%d,位模式被解释为有符号整数。

【讨论】:

    【解决方案2】:

    %d 用于有符号整数,用于 unsigned int 和 long 分别使用 %u%lu

    【讨论】:

    • 它适用于 unsigned long (ULONG_MAX) 但不应该 UINT_MAX65535 而不是 4294967925
    • 我不认为%ul 是 POSIX。你应该改用%lu
    • @Potatoswatter 好的,这让ULONG_MAX 更好,但是UINT_MAX 呢?
    • @AlexanderB.Falgui 为此,您只需要简单的%u
    • @AlexanderB.Falgui,在 64 位机器上 int 也是 4 字节长。
    【解决方案3】:

    您是否准确复制了程序的输出?你在代码中写了UNSIGNED LONG:,但是在输出中它变成了UNSIGNED LONG;unsigned long 不可能比 unsigned int 长一位

    另外,您使用了错误的类型说明符,导致undefined behavior。对于unsigned int,您必须使用%u,对于long,使用l 长度修饰符,对于ll,对于long long

    16 位计算的时代已经过去了几十年,所以int 的大小在大多数现代系统上都是 32 位,除了一些 8 位或 16 位嵌入式系统,因此范围是 [0, 232-1] 或 [0, 4294967295] 如您所见。取决于您使用的系统,long 会有不同的大小。通常在 Windows 上是 32 位类型,在 Unix/Linux 上是 64 位。 C 标准要求int 至少为 16 位,long 至少为 32 位。只有 long long 保证至少为 64 位,因此您也需要对其进行检查。

    printf("UNSIGNED CHAR:       %u    %u\n",   0U, UCHAR_MAX);
    printf("UNSIGNED SHORT:      %u    %u\n",   0U, USHORT_MAX);
    printf("UNSIGNED INT:        %u    %u\n",   0U, UINT_MAX);
    printf("UNSIGNED LONG:       %lu   %lu\n",  0UL, ULONG_MAX);
    printf("UNSIGNED LONG LONG:  %llu  %llu\n", 0ULL, ULONGLONG_MAX);
    

    如果您使用的是 Windows,unsigned int 和 unsigned long 的最大值都应为 4294967295。

    请注意,使用全大写是一个非常糟糕的选择

    【讨论】:

    • 我为您的回答 +1,因为它为我提供了有关 16、32 和 64 位的更多信息,但我缺乏这样做的声誉。如果可以的话,我会这样做。
    猜你喜欢
    • 1970-01-01
    • 2016-03-27
    • 2016-09-25
    • 1970-01-01
    • 2015-02-06
    • 2015-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多