C语言——数据的存储进阶(如果位运算不了解先看文章的开篇链接)

操作符详解_逆风路上伴有谁的博客-CSDN博客

目录

1.数据类型介绍:

C语言内置类型:

实型:float、double

整型:内置类型中实型类型之外的类型

还有三大特殊类型:

构造类型:

指针类型:

空类型:

整型存储:

原码:

反码:

补码:

2.大小端存储方式:

概念:

大端(存储)模式:

小端(存储)模式:

1.用函数实现:

2.用联合体实现

 实型的储存规则:

实例演示:

尝试实现计算机的加减:

思路:

 放一道题:

最后要说的话:

1.数据类型介绍:

C语言内置类型:

char 字符数据类型

short 短整型

int 整形

long 长整型

long long 长长整形

float 单精度浮点数

双精度浮点型

数的类型分为两大类:

实型:float、double

整型:内置类型中实型类型之外的类型

还包括

char
unsigned char
signed char


short
unsigned short [int]
signed short [int]


int
unsigned int
signed int


long
unsigned long [int]
signed long [int]
 

还有三大特殊类型:

构造类型:

数组类型

结构体类型 struct

枚举类型 enum

联合类型 union

指针类型:

int* pi;

char* pc;

float* pf;

void* pv;

空类型:

void 表示空类型(无类型)。

通常应用于函数的返回类型、函数的参数。指针类型。

数在内存中是以补码的形式存储的,所以要了解原码、反码、补码对本篇文章是很重要的。

实型在计算机存储比较复杂,放在整型后面讲。

整型存储:

由两部分组成:符号位。数值位

符号位:只表示数的正负,不表示大小。在存储是最左边的一位。1表示 - ,0表示 + 。

例如:char类型 -1 ——10000001(2)最左边的1就是符号位。1 —— 00000001(2)最左边的0就是符号位。

数值位:一个数的绝对值的二进制形式。

三个码的概念:

原码:

直接将二进制按照正负数的形式翻译成二进制就可以。

反码:

将原码的符号位不变,其他位依次按位取反就可以得到了。

补码:

反码+1就得到补码。

对于正数来说,原码、反码、补码相同
对于负数来说,

反码 :原码符号位不变,其他位按位取反(这个不知道的可以先去学习一下逻辑运算符后面也要用)

补码:数值位 + 1.

红色为数在内存的存储,为什么是14 00 00 00 呢?int是4个字节 一个字节8个bit位,即int又32个bit位,一个16进制数字是可以表示4个二进制的数字即12(16)可以表示 0001 0002。可能又有人会问20 不是00 00 00 14 吗?这个等下再说,这个和大小端存储方式有关,先不管这个,先知道是倒着存就行,一会文章后面会有解答。

 这个b是逆推的先-1在符号位不变其他位取反。

2.大小端存储方式:

概念:

大端(存储)模式:

是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中。


小端(存储)模式:

是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地址中。


我就不讲为什么这样存了,有点脱离文章,如果感兴趣可以去找相关资料。

我用的Visual Studio 2019 软件是小端存储方式。所以我能够表示小端存储方式,大端存储方式其实还是简单的。

例如:

a = 1 ,a的补码为0000 0000 0000 0000 0000 0000 0000 0001,即00 00 00 01(16)。

 

正数的原码、反码、补码相同。

为什么是两个16进制数字是连着存的?之前说过一位16进制数字可以表示4位二进制数字,两位16进制数字可以表示8位二进制,即8个bit,即1个字节,计算机的存储最小单位是字节,所以是两个16进制位存在一起。

b = -5,b的补码1111 1111 1111 1111 1111 1111 1111 1011(2),即ff ff ff fb(16).。

 数的是大端方式还是小端存储是怎么判断的呢?

我们可以用代码来观察计算机的存储方式:

1.用函数实现:

#include<stdio.h>

int W()
{
	int a = 1;

	//第一种方式
	//char* p = &a;
	//return *p;
	
	//第二种方式
	return *(char*)&a;
}

int main(void)
{
	if (W() == 1)
	{
		printf("小端存储\n");
	}
	else
	{
		printf("大端存储\n");
	}
	return 0;
}

运行结果:

2.用联合体实现

(如果不知道联合体是什么可以先去学习一下,以后可能会分享结构体联合体相关的知识,但是估计要过一段时间了,所以要想知道下面的代码是怎么实现的先其他地方去学一下,反正不是很难)

#include<stdio.h>

union W
{
	int a;
	char c;
};

int main(void)
{
	union W p;
	p.a = 1;
	if (p.c == 1)
	{
		printf("小端存储\n");
	}
	else
	{
		printf("大端存储\n");
	}
	return 0;
}

运行结果:

 实型的储存规则:


根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式:
* (-1)^S * M * 2^E
* (-1)^s表示符号位,当s=0,V为正数;当s=1,V为负数。
* M表示有效数字,大于等于1,小于2。
* 2^E表示指数位。

因为M是1到2之间的小数,所以为了M表示1.后面的数,即小数点后面的数。
float:

 double:

 S/E/M都是无符号的二进制,所以为了防止E小于0,标准规定储存时要让E加上127.

实例演示:

 一:

二:

 三:

较难的四:

1.

 2.

 3.

 4.

 5.

尝试实现计算机的加减:

思路:

代码如下:

#include<stdio.h>

int main(void)
{
	int a = -98789;
	//01010
	int b = -3;
	//10100

	//int arr[32] = { 0 };
	//int brr[32] = { 0 };

	//for (int i = 0; i <= 31; i++)
	//{
	//	arr[i] = (a >> i);
	//	brr[i] = (b >> i);
	//}
	//1 << (1 + i)	1073741824	int



	int sum = 0;
	for (int i = 31; i >= 0; i--)
	{
		if (((a >> i) & 1) + ((b >> i) & 1) == 2)
		{
			sum += (1 << (1 + i));
			if (i == 31)//这个不理解 其实我也不太理解就是调试的时候发现的看看最后两幅图
			{//主要是考虑负数 因为正数i = 31时是0 不用考虑
				sum--;
			}
		}
		else
		{
			sum += ((((a >> i) & 1) || ((b >> i)) & 1) << i);
		}
	}
	printf("%d\n", sum);

	//printf("%d\n", 1 << (32));
	return 0;
}

运行结果:

 

 测试的是a = -1, b = -1;

 不知道为什么加了个1,就很离谱。有知道的大佬可以在评论区讲解一下或者出一篇文章,@我一下。🙏🙏🙏

为什么不放0或正数相加,因为比较简单,我已经成功了,放太多图还不如自己去试一下,我实验已成功。

 放一道题:

不用加减乘除做加法_牛客题霸_牛客网

代码如下:

int Add(int num1, int num2 ) {
    // write code here
    int n1, n2;
    n1 = (num1 & num2) << 1;
    n2 = num1 ^ num2;
    while (n1 & n2)
    {
        num1 = n1; num2 = n2;
        n1 = (num1 & num2) << 1;
        n2 = num1 ^ num2;
    }
    return n1 | n2;
}

好吧~

这不是我写的,想了好几天,最终我看评论了,这是一个人的Java代码我让给粘贴来了。确实是神人,没事我也是抬着头看着这个人的。

最后要说的话:

文章有的知识点没讲,例如位运算,联合体。还有一个没解决的问题——就是实现计算机的运算的时候(两个数是负数)sum 第一位 加了1。真的感觉写一篇文章要涉及的知识太多了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值