内存函数(操作对象是字节

内存函数 ,操作对象是字节,头文件<string.h>

  1. 1.memcpy使⽤和模拟实现

source 和 destination 没有任何的重叠,

void * memcpy ( void * destination, const void * source, size_t num )

模拟实现

#include<iostream>
using namespace std;

void*my_memcpy(void*dest,void *scr,int num)
{
assert(dest&&scr);
void*ret=dest;
while (num--)
{
	*(char*)dest = *(char*)scr;
	dest = (char*)dest + 1;
	scr = (char*)scr + 1;

}
return ret;
}
  1. 2. memmove使⽤和模拟实现

source destination可以重叠

void * memmove ( void * destination, const void * source, size_t num )

模拟实现

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<assert.h>
using namespace std;
void* my_memmove(void* dest, void* scr, int num)
{
	void* ret = dest;
	assert(dest && scr);
	//从前向后拷贝
	if (dest < scr)
	{
		while (num--)
		{
			*(char*)dest = *(char*)scr;
			dest = (char*)dest + 1;
			scr = (char*)scr + 1;

		}
	}
	else //从后向前拷贝
	{
		while (num--)//num先使用,
		{
			*((char*)dest + num) = *((char*)scr + num);
		}
	}
	return ret;
}
  1. 3. memset函数的使⽤

memset函数对内存单元的设置是以字节为单位的

void * memset ( void * ptr, int value, size_t num )

例如

注意,是对字节的修改,例如

memset后                                             

  1. 4. memcmp函数的使用

int memcmp ( const void * ptr1, const void * ptr2, size_t num );

数据的存储

  1. 1. 整数在内存中的存储

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

负整数的三种表⽰⽅法各不相同

对于整形来说:数据存放内存中其实存放的是⼆进制的补码

  1. 2. ⼤⼩端字节序和字节序判断

  2. ⼤端(存储)模式:
  3. 是 指数据的低位字节内容保存在内存的⾼地址处
  4. ⼩端(存储)模式:
  5. 是 指数据的低位字节内容保存在内存的低地址处,
  6. vs上是以小端字节序存储

判断大端还是小端

void check()
{
	int a = 1;
	if (*(char*)&a == 1)//把a的地址转换为char*从而访问一个字节
		printf("小端\n");
	else
		printf("大端\n");
	
}

练习1

#include <stdio.h>
int main()
{
char a = -1;
signed char b = -1;
unsigned char c = -1;
printf("a = %d, b = %d, c = %d", a, b, c);
return 0;
}

结果;a=-1,b=-1,c=255;

练习2

#include <stdio.h>
int main()
{
char a = -128;
printf("%u\n",a);
return 0;
}

结果;4294967168

分析

#include <stdio.h>
int main()
{
char a = -128;
//-128的原码:10000000 00000000 00000000 10000000
//-128的补码:11111111 11111111 11111111 10000000 
//char a-    10000000 
//%u的形式打印:(当作无符号的整形,整形提升)
//整形提升
//因为a是char类型,有符号,所以,按照符号提升,补1;
//提升结果   11111111 11111111 11111111 10000000 
//按%u的形式输出,
//当作无符号整形,11111111 11111111 11111111 10000000就是原码。
printf("%u\n",a);
return 0;
}

练习3(变式)

#include <stdio.h>
int main()
{
char a = 128;
printf("%u\n",a);
return 0;
}

结果;4294967168

分析

与前面相比,得到的a是一样的。所以,结果一样。

#include <stdio.h>
int main()
{
char a = -128;
//128的原码:00000000 00000000 00000000 10000000
//128的补码:00000000 00000000 00000000 10000000
//char a-    10000000 
//%u的形式打印:(当作无符号的整形,整形提升)
//整形提升
//因为a是char类型,有符号,所以,按照符号提升,补1;
//提升结果   11111111 11111111 11111111 10000000 
//按%u的形式输出,
//当作无符号整形,11111111 11111111 11111111 10000000就是原码。
printf("%u\n",a);
return 0;
}

练习4

#include <stdio.h>
#include <string.h>
int main()
{
char a[1000];
int i;
for(i = 0; i < 1000; i++)
{
a[i] = -1 - i;
}
printf("%d", strlen(a));
return 0;
}

结果;255

分析

对于char类型,范围-128~127;

然而,对于超出范围的数。例如,-129

练习5

#include <stdio.h>

unsigned char i = 0;
int main()
{
for(i = 0; i <= 255; i++)
{
printf("hello world\n");
}
return 0;
}

结果;死循环

分析;unsigned char 的范围0~255;不可能超过255;

练习6

#include <stdio.h>
//X86环境⼩端字节序
int main()
{
int a[4] = { 1, 2, 3, 4 };
int *ptr1 = (int *)(&a + 1);
int *ptr2 = (int *)((int)a + 1);
printf("%x, %x", ptr1[-1], *ptr2);
return 0;
}

结果;4, 2000000

分析

知识点

1,%d-是以十进制的形式打印有符号的整数(认为我们要打印的数据在内存中是以有符号数的补码进行存诸的)

2,signed   char的取值范围是   -128~127
         无符号字符的取值范围是   0~255

3,整体提升
1,有符号整数提升是按照变量的数据类型的符号位来提升的
2、无符号整数提升,高位补0

char类型

  1. 3. 浮点数在内存中的存储

  2. 根据国际标准IEEE(电⽓和电⼦⼯程协会)754,任意⼀个⼆进制浮点数V可以表⽰成下⾯的形式:

IEEE 754规定:

对于32位的浮点数(float),最⾼的1位存储符号位S,接着的8位存储指数E,剩下的23位存储有效数字 M

对于64位的浮点数(double),最⾼的1位存储符号位S,接着的11位存储指数E,剩下的52位存储有效 数字M 

M

前⾯说过, 1 ≤ M < 2 ,也就是说,M可以写成 1.xxxxxx 的形式,默认这个数的第⼀位总是1,因此可以被舍去,

E

⾸先,E为⼀个⽆符号整数(unsignedint) 这意味着,如果E为8位,它的取值范围为0~255;如果E为11位,它的取值范围为0~2047。但是,我 们知道,科学计数法中的E是可以出现负数的,所以IEEE754规定,存⼊内存时E的真实值必须再加上 ⼀个中间数对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。

接下来,我们来看一下9.5在内存中的存储

3.2.2 浮点数取的过程

1.E不全为0或不全为1(常规情况)(常规处理)

这时,浮点数就采⽤下⾯的规则表⽰,

即指数E的计算值减去127(或1023),得到真实值,再将有效 数字M前加上第⼀位的1

E全为0

这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,有效数字M不再加上第⼀位的1,⽽是还 原为0.xxxxxx的⼩数。这样做是为了表⽰±0,以及接近于0的很⼩的数字。

E全为1

这时,如果有效数字M全为0,表⽰±⽆穷⼤(正负取决于符号位s);

运用上面的知识,来解决下面的难题吧!

题1

#include <stdio.h>
int main()
{
	int n = 9;
	float* pFloat = (float*)&n;
	printf("n的值为:%d\n", n);
		printf("*pFloat的值为:% f\n", *pFloat);
	* pFloat = 9.0;
	printf("n的值为:%d\n", n);
		printf("*pFloat的值为:%f\n", *pFloat);
		return 0;
}

输出结果;

n的值为:9
*pFloat的值为: 0.000000
n的值为:1091567616
*pFloat的值为:9.000000

解析放评论区咯!

感谢您的阅读,完结,撒花!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐