在 C 中使用无符号数据类型

Using unsigned data types in C

如何正确使用unsigned int?当用户输入 a 小于 b 时,我的函数 unsigned int sub(int num1, int num2); 不起作用。如果我简单地使用 int,我们可以期待一个否定的答案,我需要在减去之前确定哪个更大。我知道这很容易,但也许有一种方法可以使用 unsigned int 来避免这种情况?

例如,当 a = 7 且 b = 4 时,答案为 3.000000。但是当我翻转它们时,代码给了我 4294967296.000000,我认为这是一个内存地址。

#include <stdio.h>

unsigned int sub(int num1,int num2){
    unsigned int diff = 0;
    diff = num1 - num2;
    return diff;
}

int main(){
    printf("sub(7,4) = %u\n", sub(7,4));
    printf("sub(4,7) = %u\n", sub(4,7));
}

输出:

sub(7,4) = 3
sub(4,7) = 4294967293

变成负数,无符号数据类型不支持负数,所以变成大数

无符号数是无符号...这意味着它们不能为负数。 相反,它们换行(下溢或溢出)。

如果你用8位无符号做个实验,那么你可以看到0减去1的效果:

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

int main(void) {
    uint8_t i;

    i = 1;

    printf("i: %hhu\n", i);

    i -= 1;

    printf("i: %hhu\n", i);

    i -= 1;

    printf("i: %hhu\n", i);

    return 0;
}
i: 1
i: 0
i: 255

255 是 8 位无符号数可以容纳的最大值 (2^8 - 1)。


然后我们可以使用您的 4 - 7:

对 32 位无符号数进行相同的实验
#include <stdio.h>
#include <stdint.h>

int main(void) {
    uint32_t i;

    i = 4;

    printf("i: %u\n", i);

    i -= 7;

    printf("i: %u\n", i);

    return 0;
}
i: 4
i: 4294967293

4294967293 实际上是 0 - 3,换行到 2^32 - 3.


您还需要注意将整数值(sub() 函数的 return 类型)分配给 float... 通常这是要避免的事情。

见下文。 x() returns 4294967293 作为一个 unsigned int,但是它存储在一个 float... 这个 float 然后打印为 4294967296???

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

unsigned int x(void) {
    return 4294967293U;
}

int main(void) {
    float y;

    y = x();

    printf("y: %f\n", y);

    return 0;
}
y: 4294967296.000000

这个其实和float的精度有关...不可能把绝对值4294967293存到float.

unsigned int不能用来表示负变量。我相信您想要的是找到 ab 之间差值的绝对值。如果是这样,您可以使用 stdlib.h 中的 abs() 函数。 abs() 函数接受一个 int 变量 i 和 returns i.

的绝对值

之所以 unsigned int returns 在您的案例中是一个巨大的数字,是因为整数在系统中的表示方式。您将 diff 声明为 int 类型,它能够存储负值,但是当解释为 unsigned int 时,表示 -3 的相同位序列表示 4294967296 代替。

你看到的叫做无符号整数溢出。如您所述,无符号整数不能包含负数。因此,当您尝试做一些会导致负数的事情时,可能会发生看似奇怪的事情。

如果您使用 32 位整数,

  • int (int32_t) 可以保存 (-2^31) 和 (+2^31-1) 之间的数字,INT_MININT_MAX
  • unsigned int (uint32_t) 可以保存 (0) 和 (2^32-1) 之间的数字,UINT_MINUINT_MAX

当您尝试向 int 中添加一些内容,导致数字大于该类型可以容纳的数字时,它将溢出

"absolute value of the difference between a and b" 不适用于 a,b 的许多组合。任何溢出的 a-b 都是未定义的行为。显然abs(INT_MAX - INT_MIN)不会生成正确答案。

此外,使用 abs() 会调用未定义的行为,select 值为 int。当 -INT_MIN 不能表示为 int.

时,abs(INT_MIN) 是未定义的行为

计算2个int的绝对值差,减去unsigned.

unsigned int abssub(int num1,int num2){
  return (num1 > num2) ? (unsigned) num1 - num2 : (unsigned) num2 - num1;
}