整数在内存中的表达

本文通过一个形象的表盘比喻,解释了补码的概念及其在计算机中的应用,并介绍了模运算的基本原理。

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

http://bbs.chinaunix.net/thread-3765224-1-1.html


很对, 没有问题. 不过我想告诉LZ一个更容易理解的办法.

假设, 我现在只有4 bits空间. 那么这个空间最多能存放2 ^ 4, 即16个数, 也就是 0 - 15.
想像一个表盘, 这个表盘刚好有16个刻度. 这样子, 我们将上面的16个数和表盘对应起来. 对应的结果如下所示.
                              |
                              |
                               0000
                          1111      0001
                     1110                0010
                1101                          0011
           1100                                    0100
                1011                          0101
                     1010                0110
                          1001      0111
                               1000
                                    |
                                    |
本来表盘是圆形的, 结果上面看上去是菱形的. 将就看吧.
瞧: 这个表盘能够表示16个数字, 所以我们称呼16为这个表盘的模. 同理, 我们称16是4bits的模, 256是8bits的模, etc.

看到上面和下面我分别标的竖线了吗? 那代表我将这个表盘切成了两部分.
这个切法代表什么意思呢? 
我们知道表盘能够表示16个数字, 如果我认为这个表盘表示的数字都是正数, 那么我可以不切这个表盘. 不切这表盘就表示, 假设时针从0开始顺时针转, 每过一个小时, 时针就向前一格(假设一天有16个小时, 这也不是什么大事, 呵呵). 于是, 这个表盘可以表示 0 -- 15.
现在我想让这个表盘既可以表示正数, 也可以表示负数. 看, 很简单, 我把这个表盘像上面那样切开, 就像切一个馅饼一样. 我说左半部分你们代表正数吧. 右半部分你们代表负数吧. 于是一切就work了, 我们让时针顺时针转, 顺时针走一格就代表加1. 我们让时钟逆时针转, 逆时针走一格就代表减1.瞧, 正着转一格, 0000 -> 0001. 逆时针转一格, 0000 -> 1111, 等等, 1111是什么? 没错, 1111就是补码的-1. 看, 这个表盘完美地工作, 太妙了.

现在我们来做一件事情. 假设现在时针指向12点(注意, 我们这个表盘一共有16点), 就是指向1100那里. 现在我们想让时钟指到9点, 也就是1001那里. 我们可以用两种方式来做到这一点:
第一种方式是倒拨(逆时针方向)3格.
              于是我们有: 12 - 3 = 9.
第二种方式是顺拨13格.
              于是我们有: 12 + 13 = 9.
我们看看, -3是谁? 假设我们切开了这个表盘, 那么-3就是1101.
我们再看看, 13是谁? 假设我们没有切开这个表盘, 看, 13也是1101.
              于是我们有: 1100 + 1101 = 1001
于是, 明白了吗, 我不需要12 - 3, 那个减号对我来说没用. 我只管知道 1100 + 1101 = 1001就可以了. 没错, 计算机为什么用补码来表示整数,因为用补码来表示整数不需要减法, 我们只要一个硬件加法器就可以了.

同时, 我们还发现一件事情.
    (12 - 3) % 16 == 9
    (12 + 13) % 16 == 9
我们称, 12 - 3 和 12 + 13 共模同余(模16余9), 同时称, 13和3互补(在模为16的前提下), 即互为补数. 看, 算补码也很简单了.

当然了, 比如假设有32 bits, 那么模就是2 ^ 32, 如果有64 bits, 那么模就是 2 ^ 64. 很简单, 我们只需要想象一个大得多的表盘就可以了, 这挺简单的, 不是吗?

### C语言中表示整数的数据类型 在C语言中,整数可以通过多种数据类型来表示,每种类型都有其特定的用途和取值范围。以下是常见的整数数据类型及其特点: #### 1. **基本整数类型** 基本整数类型由`int`关键字表示,在大多数现代编译器中通常占用4字节(32位)[^1]。 示例代码如下: ```c #include <stdio.h> int main() { int value = 10; printf("value = %d\n", value); return 0; } ``` #### 2. **短整型 (`short int`)** 短整型用于存储较小范围的整数值,一般占用2字节(16位)。它的取值范围通常是-32768到32767。 示例代码如下: ```c #include <stdio.h> int main() { short int smallValue = 300; printf("smallValue = %hd\n", smallValue); return 0; } ``` #### 3. **长整型 (`long int`)** 长整型适用于更大的整数值,默认情况下占用4字节或更多(取决于平台),取值范围更大。例如,在32位系统上,它可能与`int`相同;而在64位系统上,则可以达到更宽的范围。 示例代码如下: ```c #include <stdio.h> int main() { long int largeValue = 2000000000L; printf("largeValue = %ld\n", largeValue); return 0; } ``` #### 4. **超长整型 (`long long int`)** 对于非常大的整数值,可以使用`long long int`类型,该类型至少支持8字节(64位),能够容纳极广的正负整数区间[-9223372036854775808, 9223372036854775807][^3]。 示例代码如下: ```c #include <stdio.h> int main() { long long int veryLargeValue = 9223372036854775807LL; printf("veryLargeValue = %lld\n", veryLargeValue); return 0; } ``` #### 5. **无符号整型 (`unsigned int`, `unsigned short`, `unsigned long`, `unsigned long long`)** 当不需要处理负数时,可以选择无符号类型以扩展正值的最大限度。这些类型的最小值始终为零,而最大值则翻倍于对应的带符号版本。 ##### 示例:无符号整型 ```c #include <stdio.h> int main() { unsigned int positiveOnly = 4294967295U; // 对应uint32_t的最大值 printf("positiveOnly = %u\n", positiveOnly); return 0; } ``` #### 6. **溢出行为** 需要注意的是,如果计算结果超出目标变量所能承载的范围,将会发生溢出现象。例如,将超过`char`容量的结果赋给`char`会引发截断错误[^2]。 示例代码如下: ```c #include <stdio.h> int main() { unsigned char a = 200; unsigned char b = 100; unsigned char c = 0; c = a + b; // 结果被截断至适合单字节的部分 printf("a + b = %d, but c stores only the last byte: %d\n", a+b, c); return 0; } ``` --- ### 总结 上述内容涵盖了C语言中的主要整数数据类型及其应用实例。不同类型的选择需基于实际需求考虑内存消耗与数值大小之间的平衡。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值