概述
在初学编程语言时,赋值语句一向被使用的很频繁,其实赋值语句就是内存函数的基本逻辑
下面我们来看一个简单赋值语句的例子:
int main()
{
int a = 1;
int b = 0;
int c = 0;b = a;
char* pa = (char*)&a;
char* pc = (char*)&c;
printf("%d %dn", b, c);
for (int i = 0; i < 4; i++)
{
*(pc + i) = *(pa + i);
}
printf("%d %dn", b, c);
return 0;
}
对于同类型变量的数据进行交换时,我们可以直接赋值 b = a;
也可以将其交给指针,在对其地址进行强制类型转换后,一个字节一个字节的进行交换。
char* pa = (char*)&a;
char* pc = (char*)&c;
for (int i = 0; i < 4; i++)
{
*(pc + i) = *(pa + i);
}
for (int i = 0; i < 4; i++)
//整形变量总共四个字节,所以这里循环的交换四次,也就交换了四个字节,正好是一个整形的大小。
我们来编译看一下结果:
可以看到,直接赋值,和每个字节按顺序赋值达到的效果是相同的。
空类型指针的作用:
在上面的例子可以看到,将int 类型的变量取地址交给char类型的指针,虽然没有错误(因为不同变量地址的大小都是一样,不同类型指针的字节大小也是相同的)所以只是赋值的话,是可以编译的过去的。但是可以看到,编译的结果有一个警告,类型不兼容。而void类型的指针来接收int类型变量的地址时,是没有警告的。
void类型的指针,可以接受任意类型变量的地址,因为他没有具体的类型,但是他也因为没有具体类型从而不能直接进行解引用。(因为指针在没有类型的情况下,解引用不知道该访问几个字节的空间)
内存拷贝函数:memcpy();
定义形式:void *memcpy( void *dest, const void *src, size_t count );
void *dest:接收目的空间首地址的指针
const void *src:接收源空间首地址的指针
size_t count :所需要拷贝的字节个数
自主实现如下:
完整代码如下:
void* my_memcpy(void* dest, const void* src, size_t num)
{
assert(dest && src);
for (int i = 0; i < num; i++)
{
*((char*)dest + i) = *((char*)src + i);
}
return dest;
}
int main()
{
int arr1[20] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
my_memcpy(arr2, arr1, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
我们以空类型的指针进行接受,然后将其强制类型转换成char类型的变量进行操作。再知道num(需要交换的字节个数),就可以对其进行一个字节一个字节的交换。
但是这个函数有一个缺点就是不能拷贝内存重叠情况的数据,我们来看下面一个例子
将数组arr1中前五个字节的变量(1,2,3,4,5)拷贝到arr1+2的位置上(3,4,5,6,7)
可以看到,得到的结果和我们不是我们想看到的,因为我们是从前到后的数据赋值,这样的话,因为有内存重叠的情况,所以前面赋值的数据会把后面需要复制的数据进行覆盖
示意图如下:
所以这里就需要引入另一个函数了
memmove();
我们再来看这样的一个例子 :
将src指向的五个整形空间的数据赋值到dest指向的五个整形空间
如果我们从后向前的赋值,这样就能很好的规避后面的数据被覆盖的情况了
这样继续下去:
当然这种情况只是适用于目的空间,比源空间的首地址大(目的空间地址在源空间地址的后面)
如果这种情况还从后向前拷贝的话,也会将后面的数据覆盖。所以这里就需要从前向后的拷贝。
1:dest>=src(目的空间在源空间后),从后向前拷贝
2:src>dest(源空间在目的空间后)从前向后拷贝
实现的代码如下
void* my_memmove(void* dest, const void* src, size_t num)
{
assert(dest && src);
if (dest >= src)
{
//从后向前
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
else
{
//从前向后
for (int i = 0; i < num; i++)
{
*((char*)dest + i) = *((char*)src + i);
}
}
return dest;
}
int main()
{
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
for (int i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
printf("n");
my_memmove(arr+2,arr,20);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
最后
以上就是眯眯眼秀发为你收集整理的c语言,内存操作函数的秘密,空类型指针含义 memcpy,memmove,memset 解析与自主实现,内附完整代码。的全部内容,希望文章能够帮你解决c语言,内存操作函数的秘密,空类型指针含义 memcpy,memmove,memset 解析与自主实现,内附完整代码。所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复