首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >c语言内存函数和数据在内存中的存储(1)

c语言内存函数和数据在内存中的存储(1)

作者头像
用户12004530
发布2026-01-23 14:56:48
发布2026-01-23 14:56:48
1050
举报

memcpy函数

代码语言:javascript
复制
void * memcpy ( void * destination, const void * source, size_t num );

函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置

这个函数在遇到 '\0' 的时候并不会停下来

如果source和destination有任何的重叠,复制的结果都是未定义的

代码语言:javascript
复制
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	memcpy(arr2, arr1, 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

使用内存拷贝函数memcpy,将整型数组arr1中前5个元素(对应20字节)的数据,复制到整型数组arr2中,最终遍历输出arr2的所有元素,对于重叠的内存,交给memmove来处理

memmove函数

代码语言:javascript
复制
void * memmove ( void * destination, const void * source, size_t num );

和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的,如果源空间和目标空间出现重叠,就得使用memmove函数处理

代码语言:javascript
复制
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr1 + 2, arr1, 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

使用memmove函数,将整型数组arr1开头的5个元素(对应20字节),复制到数组自身从第3个元素开始的位置。由于源内存和目标内存存在“重叠”,memmove会安全处理避免数据覆盖,最终输出修改后的数组

memset函数

代码语言:javascript
复制
void * memset ( void * ptr, int value, size_t num );

memset是用来设置内存的,将内存中的值以字节为单位设置成想要的内容

代码语言:javascript
复制
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
	char str[] = "hello world";
	memset(str, 'x', 6);
	printf(str);
	return 0;
}

使用内存填充函数 memset,将字符串 str 中前 6 个字符(对应 6 字节)统一填充为字符 'x',然后输出修改后的字符串

memcmp函数

代码语言:javascript
复制
int memcmp ( const void * ptr1, const void * ptr2, size_t num );

比较从ptr1和ptr2指针指向的位置开始,向后的num个字节

代码语言:javascript
复制
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
	char buffer1[] = "DWgaOtP12df0";
	char buffer2[] = "DWGAOTP12DF0";
	int n;
	n = memcmp(buffer1, buffer2, sizeof(buffer1));
	if (n > 0)
		printf("'%s' is greater than '%s'.\n", buffer1, buffer2);
	else if (n < 0)
		printf("'%s' is less than '%s'.\n", buffer1, buffer2);
	else
		printf("'%s' is the same as '%s'.\n", buffer1, buffer2);
	return 0;
}

使用通用内存比较函数memcmp,按字节逐一对两个字符串数组buffer1和buffer2的全部内容(包括字符串结束符 '\0')进行比较

整数在内存中的存储

整数的2进制表示方法有三种,即原码、反码和补码 有符号的整数,三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,最高位的⼀位是被当做符号位,剩余的都是数值位

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

 负整数的三种表示方法各不相同

原码:直接将数值按照正负数的形式翻译成⼆进制得到的就是原码

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

补码:反码+1就得到补码

对于整形来说:数据存放内存中其实存放的是补码(为什么呢?)

在计算机系统中,数值⼀律用补码来表示和存储,原因在于使用补码,可以将符号位和数值域统⼀处理; 同时,加法和减法也可以统⼀处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路

代码语言:javascript
复制
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
	int a = 0x11223344;
	return 0;
}

这就是a这个临时变量在内存中的地址和数据存储的情况,那为什么是倒序存储的?

1.因为数据在内存中存储的是二进制的补码

2.在调试去昂口中观察内存的时候,为了方便显示,显示的是十六进制的值

3.存储的顺序好像是倒过来的,这里就牵扯到大小端存储,只要把存储的数据能按需求拿出来就可以了,中间这么存储的不重要

大小端字节序和字节序判断

一般一个数据有低位和高位(个十百千万……位),而内存中的数据是从低到高存储,所以把低位的数据存储到高地址处叫做“大端字节序存储”,把高地址数据存储到高地址处叫做“小端字节序存储”

11是高位,44是低位,高位存储在高地址处叫“小端存储”(但并不代表在VS中所有数据都是小段存储)

为什么会有大小端

这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着⼀个字节,⼀个字节为8 bit 位,但是在C语言中除了8bit的 char 之外,还有16bit的 short 型,32bit的 long 型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于⼀个字节,那么必然存在着⼀个如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。 例如:⼀个 16bit 的 short 型 x ,在内存中的地址为 0x11 为高字节, 0x0010 , x 的值为 0x22 为低字节。对于大端模式,就将 0x22 放在高地址中,即 0x1122 ,那么 0x11 放在低地址中,即 0x0011 中。小端模式,刚好相反。我们常用的 0x0010 中, X86 结构是小端模式,而KEILC51 则为大端模式,很多的ARM,DSP都为小端模式,有些ARM处理器还可以由硬件来选择是大端模式还是小端模式

练习1

代码语言:javascript
复制
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int check_sys()
{
	int i = 1;
	return (*(char*)&i);
}
int main()
{
	int ret = check_sys();
	if (ret == 1)
	{
		printf("小端\n");
	}
	else
	{
		printf("⼤端\n");
	}
	return 0;
}

这里是把整型类型的数据转化为字符指针类型,因为存储的时候是存储字节,就是4个字节,一个字节占八位,两个十六进制数占八位

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-12-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • memcpy函数
  • memmove函数
  • memset函数
  • memcmp函数
  • 整数在内存中的存储
  • 大小端字节序和字节序判断
  • 为什么会有大小端
  • 练习1
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档