深入解析unsigned int 和 int

本文详细解析了有符号(int)与无符号(unsigned int)整型的区别,包括它们的取值范围、二进制表示及补码概念。通过具体实例帮助读者深入理解有符号与无符号整型在计算机中的存储方式及其对程序运行的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

就如同int a;一样,int 也能被其它的修饰符修饰。除void类型外,基本数据类型之前都可以加各种类型修饰符,类型修饰符有如下四种:
1.signed----有符号,可修饰char、int。Int是默认有符号的。
2.unsigned-----无符号,修饰int 、char
3.long------长型,修饰int 、double
4.short------短型,修饰int

我们主要来看一下signed和unsigned与int之间的联系与区别。
什么叫做有符号,什么叫做无符号
这个问题其实很简单,比如:5和-5,5没有符号,-5有符号。简单吧。但是在计算机中的这种符号可不简单。我们分别来看一下:

在说明有符号和无符号的区别之前,我们必须先知道溢出是怎么回事,因为有无符号的根本原因可以说就是因为数据出现了溢出现象导致的。

溢出:
我们知道数据在计算机中以二进制存储,并且占据一定的空间,而这个空间属于计算机分配的空间。
计算机给int分配32位或者16位(不同电脑可能不同)的空间,既然空间有限,那么数值就会有限制,就会存在最大值与最小值这一说,比如:假设int类型的分配16位,无符号类型的最大值为1111 1111 1111 1111(16个1),也就是65535,如果超过了65535,这就叫做溢出,那该怎么办? 如果要输出65536,那将会输出个什么东西呢? 下面和大家一起看一下:

疑问:有的读者会问:65535这么小啊,我记得自己在输出比65535大好多的数也能够输出啊。
解答: 那就是有无符号的定义和你电脑编译器的原因了。64位的电脑和32的电脑可是不一样的哦。而且int占几个字节是与电脑编译器有关的。不过现在大部分电脑int占4个字节,即32位,那么他的最大值可是32个1(二进制)左右的数量级,你实验过这么大的数吗?

1.无符号整型(unsigned  int)
(1)我们都知道整型是4个字节(有些编译器不同,可能会是2个),即32位,无符号整型当然也为32位。
(2)既然是32位,无符号整型的取值是32个0~32个1,即:0~4294967295
(3) 我们举个例子:32位有点长,所以我们拿16位的unsigned short int 来举例。
short int 是16位的,无符号的范围是0~65535
就拿十进制的32767(以下的所有举例均拿这个数字来说事了)来说,它的二进制为:
               0111 1111 1111 1111
对于无符号的整型32767来说,它的二进制的最高位称为数据位,即那个0就是数据位,数据位是要参与运算的,如果我们把0改成1,即16个1,它的十进制就是65535(就是2的15次方+2的14次方...一直加到2的0次方),这是不同于有符号整型的。
(4) 为了进行理解(3)中的含义,做一个程序说明:

#include <stdio.h>
main()
{
    unsigned short int a=32767,b=a+1;//定义短整型无符号
    printf("a=%u\nb=%u\n",a,b);//以无符号输出
}

定义的时候a=32767,也就是0111 1111 1111 1111,输出的依然是32767,
a+1=32768, 二进制为1000 0000 0000 0000,输入依然为32768。
根据(3)中讲解的,无符号整型的二进制最高位为数据位,数据位为0为1都是按照正常来算的。


2.有符号整型((signed)int)(1)int类型默认是有符号的,所以int实际上是signed int ,我们通常省略signed
(2)有符号整型也是32位。
(3)它的取值范围就与无符号整型不同了。它的范围是-2147483648~2147483647这个范围可以理解为无符号整型的一半变成了负数。

32位有点长,所以我们拿16位的short int 来举例。
short int 是16位的,有符号的范围是-32768~32767

这个时候可能就有人发问了,32768用二进制表示为1000 0000 0000 0000,那么这个负的32768的负号又怎么理解呢?看下面
(4)举个例子;
还是以32767为例子,它的二进制为:
      0111 1111 1111 1111
对于有符号整型32767来说,它的二进制最高位称为符号位(而不是数据位了),符号位顾名思义就是决定正负号的,规则:0是正,1为负。
(5)列举一个程序理解(4)的内容
#include <stdio.h>
main()
{
   short int a=32767,b,c,d;//定义无符号类型。
b=a+1;
c=a+2;
d=a+3;
   printf("a=%d\nb=%d\nc=%d\nd=%d\n",a,b,c,d);
}



可以看出此时的结果竟然是这个样子的。为什么呢?怎么回事?
其实在计算机中,负数是并不存在的,它是以二进制补码的形式表示和存放。什么是补码呢?

(6)什么是补码,补码的运算。
我们还是列举一个简单的例子吧!就用-6.

我们经过以上的学习已经知道负数的符号位为1,所以:
 (1)-6的二进制: 1000 0000 0000 0110(称为原码,原码是计算机显示给我的)
 (2)对原码求反码:1111 1111 1111 1001(称为反码,保持符号位不变,将原码中的0变1,1变0)
 (3)对反码加1:1111 1111 1111 1010(称为补码,补码是计算机中存储负数的形式)
在计算机中,如果存储的二进制是1111 1111 1111 1010,那么显示在我们前台的十进制数字就是-6。即:负数在计算机中是以该负数的二进制的补码形式存储的。

(7)了解了什么是补码后,再来看我们上述说的那个程序:
  32767的二进制为:0111 1111 1111 1111
我们来计算一下c的值为什么会等于-32767。
c=32767+2,c的二进制为:1000 0000 0000 0001(32767的二进制+2),c的这个二进制是在计算机中存储的补码,需要将它转换为原码,也就是将c的二进制数减一再取反。得到的二进制原码为:1111 1111 1111 1111。我们已经说过,符号位为1,表示负值,并不参加运算,所以此二进制的十进制为:-32767。
但是,上述中,c的原码的确是1111 1111 1111 1111,c在计算机中存储的补码也的确是1000 0000 0000 00010。但是-32767的由来却有另一种理解,c的补码是16位,32位编译器中有32位的二进制,也就是说在16位补码的前面还有(32-16=16)位的虚位数,并不属于计算机给short int分配的空间,但是这16位的位数当数表示正时为0,当数表示负数时为1。并且前16位的数字全部都与二进制倒数第8位的数字一致。也就是说:
  c 的补码是   1...1 1000 0000 0000 0010(1..1表示16个1)
我们可以这样计算:-2的7次方+2的1次方=-32767,这种理解普遍被大众所接受,而且避免了原码的概念。

(8)通过程序也可以发现一个规律,int的取值范围是-32768~32767,把头尾连接起来形成一个环就可以了。


参考:http://www.jb51.net/article/40518.htm

<think>好的,用户想了解不同整数类型的区别用法,特别是intunsignedint、long、long long、unsignedlong、unsigned longlong这些类型。首先,我需要回忆C/C++中的整数类型的基本知识,包括它们的存储大小、取值范围以及使用场景。首先,标准规定的整数类型的大小可能会因编译器系统架构的不同而有所变化。例如,int通常是4字节,但在某些嵌入式系统中可能是2字节。不过,现代大多数系统里,int是4字节,long可能是4或8字节,而long long通常是8字节。需要明确的是,C标准只规定了最小范围,具体实现可能更大。比如,int至少要有16位,但实际上现在都是32位。接下来是unsignedsigned的区别。unsigned类型没有符号位,所有位都用于表示数值,因此范围从0开始,而signed的最高位是符号位。例如,unsignedint的范围是0到4294967295(假设4字节),而signed int是-2147483648到2147483647。使用unsigned类型时要注意可能的溢出问题,比如减法可能导致负数,这时候结果会被解释为很大的正数,容易出错。然后,用户可能想知道何时使用这些类型。比如,当需要非负数时,比如计数器,可以使用unsigned。处理大文件或大数据时可能需要long long。此外,像intmax_tuintmax_t这样的类型是最大整数类型,适用于需要最大范围的场景,但用户的问题可能更关注基本类型。还要考虑不同平台的可移植性问题。例如,在32位64位系统中,long的大小可能不同。这时候使用固定大小的类型如int32_t、int64_t可能更好,但用户的问题中没有提到这些,可能暂时不需要深入。另外,用户可能对内存占用性能有疑问。较大的类型如long long会占用更多内存,但现代处理器处理这些类型通常效率不错,不过在大量数据时仍需考虑内存缓存的影响。 需要引用用户提供的参考资料中的内容吗?比如引用[1]提到intmax_tuintmax_t,但用户的问题是关于基本类型的区别,可能需要简单提及这些最大类型,但重点还是基本类型。引用[2]关于内存顺序,可能整数类型的使用关系不大,可以忽略。现在整理回答的结构:先按类型逐一介绍,包括存储大小、范围、典型用法,然后总结区别使用场景。可能还需要提到溢出处理类型转换的问题。 例如,int用于一般整数运算,unsigned用于非负数,long在需要更大范围时使用,long long用于非常大的数值。还要注意不同系统上的差异,比如WindowsLinux中long的大小可能不同。 另外,示例代码可能有助于说明,比如声明不同变量并赋值,但用户可能只需要文字说明。或者给出类型的最小值最大值,比如使用宏INT_MAX、ULONG_MAX等。最后,生成相关问题,如类型转换的问题、如何选择合适类型、溢出处理等。</think>在C/C++编程中,整数类型的选择直接影响数据范围、内存占用跨平台兼容性。以下是主要整数类型的对比分析: ### 一、基本整数类型对比 | 类型 | 典型字节数 | 典型范围 (32/64位系统) | 标准要求的最小范围 | |-----------------------|------------|----------------------------------|--------------------------------| | `int` | 4字节 | $-2^{31}$ ~ $2^{31}-1$ | $-32767$ ~ $32767$ | | `unsigned int` | 4字节 | $0$ ~ $4,294,967,295$ | $0$ ~ $65535$ | | `long` | 4/8字节 | $-2^{31}$ ~ $2^{31}-1$ (Windows)<br>$-2^{63}$ ~ $2^{63}-1$ (Linux) | $-2147483647$ ~ $2147483647$ | | `unsigned long` | 4/8字节 | $0$ ~ $4,294,967,295$ (Windows)<br>$0$ ~ $1.8 \times 10^{19}$ (Linux) | $0$ ~ $4294967295$ | | `long long` | 8字节 | $-9,223,372,036,854,775,808$ ~ $9,223,372,036,854,775,807$ | 标准强制要求完整64位范围 | | `unsigned long long` | 8字节 | $0$ ~ $18,446,744,073,709,551,615$ | 标准强制要求完整64位范围 | ### 二、关键差异解析 1. **符号处理** - `unsigned`类型通过放弃符号位获得双倍正数范围,例如: $$ \text{unsigned int范围} = 0 \sim (2^{32}-1) $$ - 但减法运算可能产生意外结果: ```c unsigned int a = 5, b = 10; int c = a - b; // 结果为4294967291(32位系统) ``` 2. **跨平台陷阱** `long`在不同系统中的表现差异最大: - Windows系统保持4字节(与`int`相同) - Linux/macOS系统使用8字节[^1] 3. **内存占用验证** 可通过`sizeof`运算符实测: ```c printf("long size: %zu\n", sizeof(long)); // 输出4或8 ``` ### 三、典型应用场景 1. **常规计算** ```c int score = 100; // 普通整数值 unsigned int population = 80000; // 不会出现负数的统计值 ``` 2. **大数运算** ```c long long file_size = 5LL * 1024 * 1024 * 1024; // 处理超过4GB的文件 unsigned long long hash = 0xFFFFFFFFFFFFFFFF; // 64位全1哈希值 ``` 3. **系统级编程** ```c uintptr_t address = (uintptr_t)&variable; // 指针值存储 size_t array_len = sizeof(arr)/sizeof(arr[0]); // 数组长度计算 ``` ### 四、最佳实践建议 1. **优先使用固定宽度类型**(如`int32_t`, `uint64_t`)保证跨平台一致性 2. **混合运算时**注意隐式类型转换规则: $$ \text{操作数类型提升顺序:} int \rightarrow unsigned \rightarrow long \rightarrow unsigned\ long \rightarrow long\ long $$ 3. **最大范围需求**时可使用`intmax_t``uintmax_t`[^1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值