「C语言」整型在内存中的存储 > <

目录

整型的分类

原码、反码、补码

整型的取值范围

大端、小端

截断、整型提升


整型的分类

signed char

unsigned char

signed short

unsigned short

signed int

unsigned int

signed long

unsigned long

signed表示有符号的整型,unsigned表示无符号的整型,一般情况下signed可以省略。

原码、反码、补码

对于有符号的整型,三种表示方法都分为符号位和数值位两个部分,符号位为开头的1位,符号位为0表示正数,符号位为1表示负数。需注意的是,正数的原码、反码、补码相同

原码:将数值按正负转化为二进制,该二进制数即为该数值的原码。

反码:原码的符号位不变,数值位按位取反即可得到反码。

补码:反码+1即可得到补码。

举个例子:

一个int类型占用4个字节,共32位(1byte = 8bit)

int x = 10;
//x的原码为:00000000 00000000 00000000 00001010
//因为x是正数,所以x的反码和补码与其原码相同

int y = -10;
//y的原码为:10000000 00000000 00000000 00001010
//y的反码为:11111111 11111111 11111111 11110101
//y的补码为:11111111 11111111 11111111 11110110

数据是以补码的方式存放在内存中的,所以在整型表达式计算的时候使用的并非原码,而是使用补码进行计算。

整型的取值范围

以signed char举例

signed char

00000000  ---> 0
00000001  ---> +1
00000010  ---> +2
...
01111111  ---> +127
10000000  ---> -128(规定)
10000001  ---> -127
...
11111101  ---> -3
11111110  ---> -2
11111111  ---> -1

所以signed char的取值范围为:-128~127,而unsigned char就简单了,8位一共256种情况,所以unsigned char的取值范围为:0~255。 

大端、小端

大端存储模式:数据以字节为单位,数据的低位存放在高地址处,数据的高位存放在低地址处。

小端存储模式:数据以字节为单位,数据的低位存放在低地址处,数据的高位存放在高地址处。

举个例子:

int x = -20;
//x的原码为:10000000 00000000 00000000 00010100
//x的反码为:11111111 11111111 11111111 11101011
//x的补码为:11111111 11111111 11111111 11101100
//x的补码用16进制表示为:ff ff ff ec 

 如上图所示,我们发现x的低位ec存放在了低地址处,高位存放在了高地址处,这便是小端存储。

那如何写一段代码来判断当前机器是大端还是小端呢?我们可以用char类型的指针来指向int类型的数据的地址,这样指针解引用时访问的那一个字节的空间内容会因为大小端产生差异。

	int x = 1;
	char* y = &x;
	if (*y == 1)
		printf("小端\n");
	else
		printf("大端\n");

x的补码是00000000 00000000 00000000 00000001,低位是1,如果低位放到了int起始的那个字节,也就是指针指向的那个字节,也就代表把低位的1放到了低地址处。那么指针解引用为1便是小端存储模式。而如果把高位的0放在了起始的那个字节,那便是大端存储模式。

截断、整型提升

我们都知道char存放的是字符,但如果我们把硬是数字赋值给char会发生什么?没错,截断!举个例子:

char x = -10;
//x的原码为:10000000 00000000 00000000 00001010
//x的反码为:11111111 11111111 11111111 11110101
//x的补码为:11111111 11111111 11111111 11110110
//但x的类型是char,只有8位,所以从数据的低位发生截断
//截断后:11110110

而当我们用x进行计算时,因为C的整型算术运算总是至少以缺省整型类型的精度来进行的。为了获得这个精度,表达式中的字符短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升。比如下面这串代码:

char x = -10;
//截断后:11110110

int y = 20;
//y的补码:00000000 00000000 00000000 00010100

int z = x + y;
//计算时x需要整型提升,因为x的类型是有符号的char,所以整型提升的时候高位补符号位
//x提升后:11111111 11111111 11111111 11110110
//y的补码:00000000 00000000 00000000 00010100
//z的补码:00000000 00000000 00000000 00001010
//因为z为正数,所以z的原码与补码一致,计算结果为z=10

 乍看上去整型提升似乎没啥存在感,不就是-10 + 20 = 10嘛,那下面例子整型提升的存在感就很强了:

char x = 1;
printf("  x:%u\n", sizeof(x));//sizeof求类型所占字节大小
printf("x+0:%u\n", sizeof(x+0));

short y = 1;
printf("  y:%u\n", sizeof(y));
printf("y+0:%u\n", sizeof(y+0));

结果如下:

 当x、y未参与计算时,为其本来的类型大小,char是1个字节,short是2个字节。但当x、y参与计算,就会发生整型提升,变为int类型的大小,也就是4个字节。还有要补充的一点就是,整数提升时高位补什么取决于该数值的类型,若是有符号数,则提升符号位,若不是,则提升0。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言整型常量通常被存储在符号表。符号表是编译器在编译过程用来管理标识符(如变量、函名等)的据结构。 整型常量是在程序直接使用的常值,例如:`int num = 10;` 的 `10` 就是一个整型常量。当编译器遇到整型常量时,它会将其添加到符号表并为其分配内存空间。 在符号表整型常量的内存分配是由编译器决定的。通常情况下,整型常量被存储在栈区或据区。 - 如果整型常量位于函内部的局部变量,它通常会被分配在栈区。栈区是用来存储局部变量和函调用信息的内存区域,它在函调用结束后会被自动释放。 - 如果整型常量是全局变量或静态变量,它通常会被分配在据区。据区是用来存储全局变量、静态变量和字符串常量等据的内存区域,它在程序运行期间一直存在。 以下是一个示例,展示了整型常量存储在不同内存区域的情况: ```c #include <stdio.h> int globalVar = 20; // 全局变量 void function() { int localVar = 30; // 局部变量 printf("Global variable: %d\n", globalVar); printf("Local variable: %d\n", localVar); } int main() { function(); return 0; } ``` 在上面的例子,全局变量`globalVar`和局部变量`localVar`都是整型常量。全局变量`globalVar`存储据区,而局部变量`localVar`存储在栈区。当函调用结束后,局部变量会被自动释放。 需要注意的是,整型常量本身并不占用存储空间,它们只是在编译时被编译器用于生成目标代码的相应指令。在运行时,整型常量的值会被加载到内存相应的位置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值