编程技能:字符串函数13,memcpy
编程技能:字符串函数
专栏导航
本节文章分别属于《Win32 学习笔记》和《MFC 学习笔记》两个专栏,故划分为两个专栏导航。读者可以自行选择前往哪个专栏。
(一)WIn32 专栏导航
(二)MFC 专栏导航
本节前言
之前学习的字符串函数的名字,都是以 str 开头。本节和下一节所要学习的函数,都是以 mem 开头。
mem,是 memory 的缩写。memory,英文为【记忆】的意思。而在计算机领域,它指的是存储器,通常指内存。这个内存,它和物理内存条不见得是一回事。在这里,我对内存这一概念不详细展开,大家可以自行查看。
本节,我们要去学习的,是 memcpy 函数。mem,是 memory 的简写,内存的意思。cpy,是 copy 的简写,复制的意思,也可以音译为拷贝。合起来,memcpy,主要是用于拷贝内存。我们也可以将 memcpy 函数称作【内存拷贝】函数。
我们开始本节的正式内容的学习。
一. memcpy 基本介绍
想要使用 memcpy 函数,如果是想要在 C 语言里面使用,那么,你需要有【#include <string.h>】一行。如果是想要在 C++ 里面使用,你需要有【#include <cstring>】一行。
下面,是 memcpy 函数的原型声明。
void * memcpy(void * dest,const void * src, int n);
我在这里所列的原型声明,它只是我从 Linux 0.12 内核中提取出来的一种声明而已。在 Visual Studio 里面,它的声明形式不是这样子的。但是呢,我在这里列举出来的声明,它是可用的。
此函数的功能,是从 src 所指示的源地址开始,拷贝 n 个字节的内容到 dest 所指示的目标地址中。返回值为 dest 的值。
假定,有如下代码。
void * pdest;
void * psrc;
void * pres;
int count;
pdest = (void *)0x2000;
psrc = (void *)0x1000;
count = 4;
pres = memcpy(pdest, psrc, count);
在上面的代码中,涉及了一个大家可能会觉得疑惑的用法。
pdest = (void *)0x2000;
将 0x2000 强制转换为【void *】类型,为啥要这么转换呢?
因为 pdest 是【void *】类型的。单纯的整数,与指针值,在数值上是相同的。然而,指针值,是可以进行一些个指针所专有的操作的,而单纯的整数则不行。
比如说,一个【int *】类型的指针变量 p,可以这么来使用它,p[3] 。而对于一个【int】型变量 i,则不可以用作 i[3] 。
将一个单纯的整数转换为指针类型,它的意思是,告诉编译器,我们要将某一个整数看作是指针值,而不是将其看作单纯的整数。同时,我们也很可能会使用这个指针值进行一些个指针专有的操作。
上面的代码块中的 memcpy 函数的意思是,从内存的 0x1000 位置开始,拷贝 4 个字节,到 0x2000 位置。具体拷贝方式如下。
将内存 0x1000 位置的一字节内容,拷贝到 0x2000 中。
将内存 0x1001 位置的一字节内容,拷贝到 0x2001 中。
将内存 0x1002 位置的一字节内容,拷贝到 0x2002 中。
将内存 0x1003 位置的一字节内容,拷贝到 0x2003 中。
从某一内存地址 p 开始,拷贝 n 个字节的内容到别的地方去,它指的是,将 p,p+1,p+2,p+3,…… p+(n-1) 这些位置的内容都给拷贝出去。
将某某内容,拷贝 n 个字节到内存地址 p 中,他指的是,依次地,将不同的字节的内容,拷贝到 p,p+1,p+2,p+3,…… p+(n-1) 这些内存位置里面。
一个 int 型变量,一般地,它占据的是 4 个字节的内存空间。假定,某一个 int 型变量的起始内存地址是 0x1000,则这个变量所使用的 4 个内存地址为:0x1000,0x1001,0x1002,0x1003 。
某一种变量,它占据着 k 个字节的内存空间,且它的起始地址为 p,则它所占据的内存地址为:p,p+1,p+2,p+3,…… p+(k-1) 。
内存是什么?你可以将内存看作是一个大的数组。每一个数组元素,是一个字节的容量。而内存地址,就是这个大数组的下标。
平时所见到的物理内存,是一个长条形的电路板。而对于编程人员来讲,我们是将内存理解为一个容量非常大的字节数组。一个512M 的内存,它的容量为 1024 × 1024 ×512 。则这个内存的地址序列为:0,1,2,3,…… 1024 × 1024 × 512 - 1 。
经过这样的讲解,我想,对于内存拷贝的功能,你应该是能够大致理解了。
关于内存的编程模型的问题,以后,我若是有机会去写汇编语言的教程的话,那么,我还会去专门讲它的。这一次,是因为本节需要使用内存模型,所以,我临时地讲了一点。
接下来,我们给出 C 语言代码实例和 C++ 代码示例。
二. memcpy 的 C 语言代码示例
代码如下。
#include <stdio.h>
#include <string.h>
#ifndef NUM
#define NUM 5
#endif
int main(void)
{
int arr01[NUM] = {10, 20, 41, 69, 100};
int arr02[NUM];
int count, i;
count = sizeof(arr02);
memcpy(arr02, arr01, count);
for (i = 0; i < NUM; i++)
{
printf("arr01[%d] = %d, arr02[%d] = %d\n", i, arr01[i], i, arr02[i]);
}
return 0;
}
代码的开头部分,有定义 NUM 宏。我用它来定义数组元素的个数。
在程序中,我还用到了 sizeof(数组名) 的格式的代码。
sizeof(数组名),所得到的,是这个数组的全部元素所占用的字节数。
假定,我们声明的同时初始化了一个数组,其中的每一个元素的类型为 int 类型。这个数组,我们给它设置了 10 个元素个数。而在初始化的时候,我们给它初始化了前 3 个元素,后面的 7 个元素,我们并未初始化。在这种情况下,sizeof(数组名),得到的,是 40,而不是 12 。
也就是说,sizeof(数组名),它是说,在声明的时候,它共有多少个元素,则求得的结果,是表达式【声明时的总的元素个数 × 每一个元素所占的字节数】的乘积。
其余的代码,大家自行阅读吧。
运行结果如下。

三. memcpy 的 C++ 代码示例
代码如下。
#include <iostream>
#include <cstring>
using namespace std;
#ifndef NUM
#define NUM 5
#endif
int main(void)
{
int arr01[NUM] = {10, 20, 41, 69, 100};
int arr02[NUM];
int count, i;
count = sizeof(arr02);
memcpy(arr02, arr01, count);
for (i = 0; i < NUM; i++)
{
cout << "arr01[" << i << "] = " << arr01[i] << ", ";
cout << "arr02[" << i << "] = " << arr02[i] << endl;
}
return 0;
}
结束语
本节的内容,应该是不难的。你可能掌握不准的地方,是【sizeof(数组名)】与【pdest = (void *)0x2000】两处代码。
看一看,想一想,应该还是能看懂的。
学习愉快。
专栏导航
本节文章分别属于《Win32 学习笔记》和《MFC 学习笔记》两个专栏,故划分为两个专栏导航。读者可以自行选择前往哪个专栏。
(一)WIn32 专栏导航
(二)MFC 专栏导航
更多推荐
所有评论(0)