C语言——整形数据的存储


前言

C语言中整形数据的存储主要有三个重点。1、原反补码 2、大小端 3、整形截断和提升


一、原反补码

原码、反码、补码是计算机中对数字的二进制表示方法。

原码:将最高位作为符号位(0表示正,1表示负),其它数字位代表数值本身的绝对值的数字表示方式。

反码:如果是正数,则表示方法和原码一样;如果是负数,符号位不变,其余各位取反,则得到这个数字的反码表示形式。

补码:如果是正数,则表示方法和原码一样;如果是负数,则将数字的反码加上1(相当于将原码数值位取反然后在最低位加1 。
用八位二进制数举个例子:

原码反码补码
1000000010000000100000001
-1100000011111111011111111

那么为什么会有原反补码存在呢? 原因是计算机只有加法器,没有减法器。
在计算器中,所有的减法计算都必须用加法进行,通过被减数的补码代替被减数,可以把减法转变为加法运算。
用上例中的两数相加试一试。
如果用原码计算:
在这里插入图片描述
可以看到答案是-2,但这并不是正确的结果,因此聪明的计算机先驱们创造了补码,利用补码相加:
在这里插入图片描述
这样一来,计算的答案就正确了!

二、大小端

计算机对数据的存储方式可分为大端存储和小端存储模式。

采用大小模式对数据进行存放的主要区别在于在存放的字节顺序,大端方式将高位存放在低地址,小端方式将低位存放在低地址。采用大端方式进行数据存放符合人类的正常思维,而采用小端方式进行数据存放利于计算机处理。到目前为止,采用大端或者小端进行数据存放,其孰优孰劣也没有定论。

在一个处理器系统中,有可能存在大端和小端模式同时存在的现象。这一现象为系统的软硬件设计带来了不小的麻烦,因此,判断系统到底是大端还是小段存储是非常终于重要的。
设计一个函数判断大小端:

代码一:
void bigorsmall()
{
int a = 1;
char b = *(char*)&a;
if(b==1)
	printf("小端\n")
else
	printf("大端\n");
}
代码二(利用联合体判断):

int bigorsmall()
{
	union
	{	int i;
		char c;
	}un;
	un.i = 1;
	return un.c;
}
如果返回1,则说明是小端机,0则是大端机。

三、整形的截断与提升

整形的截断和提升是给整形赋值时可能会发生的事件。

1.整形截断

机制将字节数多的数据类型赋给字节数少的数据类型时触发
效果截取低位的数据,舍弃高位数据

2.整形提升

机制将字节数少的数据类型赋给字节数多的数据类型时触发
效果1.无符号数->向多出的高位补0 ----------------- 2.有符号数->补符号位

举例说明

整形截断
int main()
{
  unsigned char a = 200;
  unsigned char b = 100;
  unsigned char c = 0;
  c = a + b;
  printf(%d ”, c);
  return 0;
}

上面代码的输出结果是44。原因是由于200+100=300,但无符号char型的最大值是255,300的二进制数是100101100此时传值就会发生截断,舍弃最高位的1,剩下的低八位就是44了。

整形提升

 int main()  
 {  
    char a = -128;  
    printf("%u\n",a);  
    return 0;  
}

上面代码的输出结果如下
在这里插入图片描述
这里为什么会输出一个这么大的数字呢,我们把它转换成二进制看看,转换成二进制的结果是11111111 11111111 11111111 10000000,可以看到前面那么多1的原因应该是进行了补位。

这就是整形提升的效果,来分析一下这段代码。
这里给a赋值的第一步首先进行了整形截断,-128的二进制是110000000,补码是110000000,截断后变成10000000(8位二进制数)。

然后需要%u打印时就要进行整形提升到32位,补充符号位后就变成了11111111 11111111 11111111 10000000,因此就能理解输出结果为什么这样了。

### C语言数据存储形式 #### 静态与动态存储类别 在C语言里,变量依据其声明方式被划分为两种主要的存储类别:静态存储和动态存储。对于采用静态存储方式的变量,在编译期间即完成内存空间预留工作,并且在整个应用程序执行周期内持续占用这部分资源,这意味着这类变量拥有固定的内存位置[^1]。 相反地,那些遵循动态存储机制的对象会在程序实际运行时才获取必要的内存单元,它们的存在期限依赖于具体的调用场景或是作用域范围内的活动状态变化而定。 #### 实型变量内部表示法 针对实数类型的处理上,C语言提供了`float`单精度浮点数以及`double`双精度浮点数两种选项。这些数值按照IEEE754标准来编码保存,具体来说由三部分组成:符号位(sign bit)、指数偏移值(exponent bias value)和尾数(mantissa),这使得计算机能够有效地表达非常大或极小的小数[^2]。 #### 整形常量及其补码表现形式 当涉及到负整数如`b=-10`这样的赋值操作时,系统会利用二进制补码体系来进行记录。该例子展示了如何通过原码、反码最终形成补码的过程,其中每一个步骤都反映了不同层面的信息压缩策略以适应硬件底层需求[^3]: ```c #include<stdio.h> int main(){ int b = -10; } ``` 在此基础上,可以看到`-10`对应的机器级描述如下所示: - **原码**: `10000000000000000000000000001010` - **反码**: `11111111111111111111111111110101` - **补码**: `11111111111111111111111111110110` #### 结构体成员排列规则 除了基本的数据类型外,复合结构也是构成复杂应用不可或缺的一部分。例如定义了一个名为`Stu`的学生信息模板,它包含了年龄(`age`)字段和姓名数组(`name[20]`)。值得注意的是,为了提高访问效率并满足特定平台的要求,编译器可能会调整各组成部分之间的相对距离,这就是所谓的“内存对齐”,从而影响到整体对象所占据的实际字节数目[^4]。 #### 扩容转换原则概述 最后提到的一点是关于不同类型间相互转化的原则之一——扩容转换。这种做法旨在确保参与算术运算的不同宽度的操作数之间不会因为尺寸差异而导致计算结果失真或者丢失有效数字。比如当遇到`int`与`long`混合运算的情况时,前者会被临时提升至后者规格再继续后续流程[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值