「地表最强」C语言(一)基本数据类型

环境:CLion2021.3;64位macOS Big Sur


地表最强C语言系列传送门:
「地表最强」C语言(一)基本数据类型
「地表最强」C语言(二)变量和常量
「地表最强」C语言(三)字符串+转义字符+注释
「地表最强」C语言(四)分支语句
「地表最强」C语言(五)循环语句
「地表最强」C语言(六)函数
「地表最强」C语言(七)数组
「地表最强」C语言(八)操作符
「地表最强」C语言(九)关键字
「地表最强」C语言(十)#define定义常量和宏
「地表最强」C语言(十一)指针
「地表最强」C语言(十二)结构体、枚举和联合体
「地表最强」C语言(十三)动态内存管理,含柔性数组
「地表最强」C语言(十四)文件
「地表最强」C语言(十五)程序的环境和预处理
「地表最强」C语言(十六)一些自定义函数
「地表最强」C语言(十七)阅读程序

一、基本数据类型

1.1 基本数据类型及其所占字节

数据的分类:

1.整型		2.浮点型		3.构造类型(自定义类型):数组、结构体、枚举、联合体		4.指针型
5.空类型void,可用于函数返回值void test()、函数参数void test(void)、指针void* p

七种基本类型:char、short、int、long、long long、float、double.
在32位编译器下经sizeof测试后的占用空间情况如下:

数据类型占用空间大小 (byte)
char1
short2
int4
long4
long long8
float4
double8

在64位编译器下经sizeof测试后的占用空间情况如下:

数据类型占用空间大小 (byte)
char1
short2
int4
long8
long long8
float4
double8

int:可定义成十进制、八进制或者十六进制,输出时用相应的格式控制符号就可以,可以与char相互转换。但要注意,若int为负数,不能转换,因为ASCLL 码没有负数。

	int a = 0x32;//定义16进制以0x开头
	int b = 017;//定义8进制以0开头
	printf("%d\n" ,a + b);//%d代表输出10进制,%u代表输出无符号10进制
	printf("%x\n", a + b);//%x代表输出16进制
	printf("%o\n", a + b);//%o代表输出8进制
	printf("%c\n", a + b);//%c代表输出字符,根据ACSLL码找到相应的字符
	

float和double:若只给出一个浮点数(指常量而非定义的变量),那么这个浮点数默认为double类型,可以在后边加f来变成float类型。

3.0;//double类型		
5.0f;//float类型
float a = 1;//float类型	(通过sizeof判断,结果为4)

1.2 整数的存储

1.整型在内存中以补码形式存放,注意char也是整型:

charunsigned/signed		shortunsigned/signed		intunsigned/signed		longunsigned/signed

short和int默认为signed型,而char默认为有符号还是无符号C语言没有规定,取决于编译器,不过大部分编译器默认是signed。

用补码存储的原因:
CPU只有加法器而没有减法器,使用补码可以将符号位和数值域统一处理;同时加法和减法也可以统一处理;此外,补码与原码相互转换的运算过程是相同的,不需要额外的硬件电路。
正整数的原码=反码=补码;
负整数反码为其原码除符号以外按位取反,补码为反码加1。因此从补码得到原码一般思路是先减1,再除符号位外按位取反,当然是可行的。其实将补码除符号位按位取反再加1,也可以得到原码,这样做的好处是统一了原码与补码的转换过程。

2.大端存储与小端存储
大端字节序和小端字节序:以字节为单位考虑数据地存储顺序。
大端字节序:把数据的高位字节序的内容存放在低地址处,低位字节序的内容存放在高地址处。
小端字节序:把数据的低位字节序的内容存放在低地址处,高位字节序的内容存放在高地址处。

判断当前机器采用大端存储还是小端存储:

int byteSqu()
{
	int a = 1;
	char* p = (char*)&a;
	return *p;//大端返回0,小端返回1
}

3.练习:
(1)

	char a = -1;
	signed char b = -1;
	unsigned char c = -1;
	//10000000 00000000 00000000 00000001 -> 11111111 11111111 11111111 11111110 -> 11111111 11111111 11111111 11111111
	//-> 11111111 - a -(整型提升) 11111111 11111111 11111111 11111111 = -1
	//11111111 - b -(整型提升) 11111111 11111111 11111111 11111111 = -1
	//11111111 - c -(整型提升) 00000000 00000000 00000000 11111111 = 2^8 - 1 = 255
	printf("%d %d %d", a, b, c);

有关整型提升,见地表最强C语言汇总(八)操作符8.11
(2)

	char a = -128;
	//10000000 00000000 00000000 10000000
	//11111111 11111111 11111111 01111111
	//11111111 11111111 11111111 10000000
	//10000000 - a(整型提升,注意是按照原变量的类型确定符号) - 11111111 11111111 11111111 10000000 - 在%u的视角下,此数为正数,其补码就是原码
	printf("%u\n", a);//4294967168

(3)

	char a = 128;
	printf("%u\n", a);//4294967168

char类型的取值范围:
有符号:-128 – 127(10000000被解析成-128)且127 + 1 = -128
无符号:0 – 255
在这里插入图片描述
(4)

	int i = -20;
	unsigned int j = 10;
	//10000000 00000000 00000000 00010100 -> 11111111 11111111 11111111 11101100
	//00000000 00000000 00000000 00001010
	//11111111 11111111 11111111 11101100
	//11111111 11111111 11111111 11110110 -> 100000000 00000000 00000000 00001010 = -10
	printf("%d\n", i + j);

(5)

	unsigned int i = 0;
	for (i = 9; i >= 0; i--)//死循环
		printf("%u\n", i);//打印是正负再打印的时候不取决于i本身,而是取决于打印的格式

(6)

	char a[1000];
	int i = 0;
	for (i = 0; i < 1000; i++)
		a[i] = -1 - i;
	//-1 -2 -3 ... -128 127 126 ... 1 0 -1 -2 -3 ...
	printf("%d", strlen(a));//255
	//char:超出范围的数据若为正数,-256;若为负数,+256

(7)

	unsigned char i = 0;
	for (i = 0; i <= 255; i++)//死循环,无符号char最大值为255
		printf("hello world\n");

1.3 浮点数的存储

IEEE754标准规定,任意一个二进制浮点数V可以表示为下面的形式:
1.(-1)^S * M * 2^E;
2.(-1)^S表示符号位,S=0时V为正数;S=1时V为负数;
3.M表示有效数字,大于等于1,小于2;
4.2^E表示指数位;
其中:
1.对于32为浮点数,即float,最高一位为符号位,接着是8位指数位E,最后是23位有效数字位M,
对于64位浮点数,即double,最高一位为符号位,接着是11位指数位E,最后是52位有效数字位M;
2.M:由于1<=M<2,因此M小数点前必为1,没有必要存储,所以只存小数点后边的数据即可,这样M就可以存储24(53)位有效位。
3.E:E为无符号整数,但是指数可正可负,因此E存入内存的值为E的真实值加上一个中间数,若E为8位,这个中间数为127;若E为11位,这个中间数为1023。
无符号8位可以表示的范围:0 – 255,减去127后:-127 – 128,这就是float实际能表示的指数的范围
无符号11位可以表示的范围:0 – 2047,减去1023后:-1023 – 1024,这就是double实际能表示的指数的范围。
4.数据根据指数E从内存中取出的三种情况:
(1)E不全为0且不全为1:
E(真实) = E -127(1023),再将有效数字M加上第一位的1;
(2)E全为0:
此时真实的E很小,规定E(真实) = 1 - 127(1023),有效数字M不需加上第一位的1,而是还原为0.xxxxxx,用来表示±0或很接近0的数;
(3)E全为1:
根据符号位来表示±无穷大

练习:

float f =  5.5f;
//101.1 --> 1.011 * 2^2
//S = 0		E = 2			M = 1.011	---真实值
//S = 0		E = 129			M = 011		---实际存储
//0			10000001		01100000000000000000000
//01000000 10110000 00000000 00000000
//40 b0 00 00
	int n = 9;
	//00000000 00000000 00000000 00001001
	float* pFloat = (float*)&n;
	printf("n的值为:%d\n", n);
	printf("*pFloat的值为:%f\n", *pFloat);//以浮点数的视角打印结果
	//		S    E               M
	//存:	0	 00000000		 00000000000000000001001
	//取:	0	 1-127=-126		 0.00000000000000000001001
	//0.00000000000000000001001 * 2^-126	-->	0.000000
	*pFloat = 9.0;//以浮点数的视角存储9.0
	//1001.0  --> 1.001 *2^3
	//			S	E			M
	//真实 		0	00000011	00100000000000000000000
	//实际存储  0	10000010	00100000000000000000000
	//int取		01000001 00010000 00000000 00000000  -- 1,091,567,616
	printf("n的值为:%d\n", n);
	printf("*pFloat的值为:%f\n", *pFloat);
  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值