一、整型家族
char
unsigned char signed char
short
unsigned short [int] signed short [int]
int
unsigned int signed int
long
unsigned long [int] signed long [int]
或许有朋友会疑问,为什么char是整型家族的?它不是字符型的吗,那是因为
char的存储使用ASCII码值进行存储的,ASCII码值都是整数,故可以看做整型家族的成员
二、原码、反码、补码详解
(1)符号位
在讲这些之前,得先明白什么是符号位,符号位就是专门用来存储数据符号信息的位
c语言规定,数据存储中数据的最高位为符号位,如int a=1;
它的原码是00000000000000000000000000000001
0就是它的符号位,而如果符号位是1的话,那么这个数据便是负数
总结:符号位是数据的最高位,符号位为0为正数,为1为负数
(2)原、反、补转换
原码就是一个数据本来的样子转换成二进制的形式,如int a=128;
此时a的原码就是00000000000000000000000010000000
有符号数的原、反、补码之间的转换跟符号位是息息相关的
正数的原码、反码、补码是一样的,因此在计算的时候可以不用多费心思
不要问我为什么正数的原、反、补时一样的,1+1为什么等于2我真没法解释。
回归正题,我们讲一下负数的原、反、补怎么来,如int a=-1;
//10000000000000000000000000000001原 //11111111111111111111111111111110反 //11111111111111111111111111111111补
原码很好来,就是这个数据的二进制形式
那么反码是什么呢?反码,反码顾名思义,就得来点反的,反码就是在符号位不变的情况下将其他位“反”过来即0变1,1变0
补码就是在反码的基础上加1即可
再提一嘴,无符号数由于没有负数一说,因此它的原、反、补和正数一样都是原码=反码=补码。
三、整型提升
关于整型提升,首先要明确的就是对象,什么样的数据会整型提升呢?其次要明确的是条件,在什么条件下数据会进行整型提升呢?最后我们会简单的阐述一下为什么会有整型提升这一步,这一步有什么用?
(1)什么样的数据会整型提升?
顾名思义,整型提升是用在小于整型这个数据类型的数据类型上的,如char,short这些一个字节空间,两个字节空间的变量(int存放的是四个字节),也就是说比int短的都是整型提升的对象。
(2)什么情况下会整型提升?
简单点说就是,你在使用小于int类型的变量时,又要用int的方式进行数据的取出时,这个时候就会涉及到整型提升。
如以下代码
#include<stdio.h> int main() { char a = -1; printf("%u", a); }
其实在这里就有了整型提升,只是你看不出来,但是当它此时我们打印的是无符号数时,整型提升便能够体现出来了如这个代码
#include<stdio.h> int main() { char a = -1; printf("%u", a); }
可以猜一下这个打印出来是什么。
猜错了吧,为什么会这样呢?这个就跟整型提升有关了,容我先卖个关子,到习题讲解时我们会详细叙述。
(3)为什么要整型提升,有什么用?
以笔者浅薄的认识,这是用来提高精度的,至于这个精度的提高体现在哪里,如何展现出来,恕笔者学艺不精,还讲不出个所以然。
四、大小端存储
(1)什么是大小端存储?
大端存储 低位字节序存放到高位地址
小端存储 低位字节序存放到低位地址
什么是高位字节序?什么是低位字节序呢?
很简单,如12345这个数5就是它的最低位字节序,1就是它的最高位字节序
再如987654这个数,4就是它的最低位字节序,9就是它的最高位字节序
以下这张图片是在vs2019编译器下对int a=0x11223344数据内存的展现
不难看出,高位字节序存储在了高位地址,是小端存储。
(2)大小端检测小程序
int a=1;
数据a的原码就是00 00 00 01(十六进制下的)
高位 低位
不难看出,如果我们通过强制转换,做一个char类型的指针,强制将int a的地址存放在cha指针类型中,那么我们就可以只操作一个字节的内存,然后通过这个字节的内容看出编译器是大端存储还是小端存储。注:取地址时总是取到数据的低位地址
如果是大端存储,那么这个字节存储的就是00(将高位字节序内容存储到了低位地址)
如果时小端存储,那么这个字节存储的就是01(将低位字节序内容存储到了高位地址)
上代码
int main() { int a = 1; char* a1 = (char*)&a; if (*a1 == 0) { printf("大端\n"); } else if(*a1 == 1) { printf("小端\n"); } }
五、习题练习
回到之前讲整型提升遗留下的问题
//10000000000000000000000000000001原 //11111111111111111111111111111110反 //11111111111111111111111111111111补 //11111111 char长度不够,截断 //11111111111111111111111111111111符号位是1整型提升得补码 //整型提升是根据原来数据类型的符号位来提升的,原来的数据是有符号数提升的时候便是相应符号 //位,无符号数整型提升补0至32位 //11111111111111111111111111111111无符号数原反补相同,故最终值就是这个
#include<stdio.h> int main() { char a = -1; printf("%u", a); }
再来一道
//00000000000000000000000010000000原,反,补相同 //10000000发生截断 //11111111111111111111111110000000整型提升得补码 //11111111111111111111111110000000无符号数原,反,补相同
#include<stdio.h> int main() { char a1 = 128; printf("%u\n", a1); }
好了,今天的分享就到这里结束了,祝友友们前程似锦