在 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
不能用来表示负变量。我相信您想要的是找到 a
和 b
之间差值的绝对值。如果是这样,您可以使用 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_MIN
和 INT_MAX
- unsigned int (
uint32_t
) 可以保存 (0) 和 (2^32-1) 之间的数字,UINT_MIN
和 UINT_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;
}
如何正确使用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
:
#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
不能用来表示负变量。我相信您想要的是找到 a
和 b
之间差值的绝对值。如果是这样,您可以使用 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_MIN
和INT_MAX
- unsigned int (
uint32_t
) 可以保存 (0) 和 (2^32-1) 之间的数字,UINT_MIN
和UINT_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;
}