文档章节

第16章 C预处理器和C库 16.12 string.h库中的memcpy()、memmove()

idreamo
 idreamo
发布于 2017/07/31 07:18
字数 865
阅读 12
收藏 0

不能把一个数组的值直接赋给另一个数组,因此,我们使用循环把数组中的元素逐个复制到另一个数组。

一个例外情况是:可以使用strcpy()和strncpy()函数复制字符数组memcpy()和memmove()函数为复制其他类型的数组提供了类似的便利工具。下面是这两个函数的原型:

void *memcpy(void *restrict s1,const void *restrict s2,size_t n);
void *memmove(void * s1,const void *s2,size_t n);

这两个函数均从s2指向的位置复制n字节数据到s1指向的位置,且均返回s1的值两者间的区别由关键字restrict造成,即memcpy()可以假定两个内存之间没有重叠。memmove()则不作这个假定,因此,复制过程类似于先将所有字节复制到一个临时缓冲区,然后再复制到最终目的地。如果两个区域存在重叠时使用memcpy()会怎么样呢?其行为是不可预知的,即可能正常工作也可能失败。在不应该使用memcpy()时,编译器不会禁止使用memcpy()。因此,使用memcpy()时,您必须确保没有重叠区域。这是程序员的任务的一部分。

这两个函数可对任何数据类型进行操作,因此两个指针参数为void类型指针。接受各种类型指针导致函数无法知道要复制的数据类型。因此,这两个函数使用第三个参数来指定要复制的字节数。注意,对数组而言,字节数一般不等于元素个数。因此,如果复制10个double类型值组成的数组,那么应使用10*sizeof(double)作为第三个参数,而不是10.

程序清单16.17显示了一些使用这两个函数的示例。

程序清单16.17  mems.c程序

//mems.c  --使用memcpy()和memmove()函数
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define SIZE 10

void show_array(const int ar[],int n);

int main()
{
    int values[SIZE] = {1,2,3,4,5,6,7,8,9,10};
    int target[SIZE];
    double curious[SIZE / 2] = {1.0, 2.0, 3.0, 4.0, 5.0};

    puts("memcpy() used: ");
    puts("values (original data): ");

    show_array(values,SIZE);
    memcpy(target,values,SIZE*sizeof(int));
    puts("target(copy of values): ");
    show_array(target,SIZE);

    puts("\nUsing memmove() with overlapping ranges: ");
    memmove(values + 2,values,5*sizeof(int));
    puts("values -- elements 0-5 copied to 2-7: ");
    show_array(values,SIZE);

    puts("\nUsing memcpy() to copy double to int: ");
    memcpy(target,curious,(SIZE/2)*sizeof(double));
    puts("target -- 5 double into 10 int positions: ");
    show_array(target,SIZE);

    return 0;
}

void show_array(const int ar[],int n)
{
    int i;

    for(i=0;i<n;i++)
    printf("%d ",ar[i]);
    putchar('\n');
}


输出如下:

memcpy() used:
values (original data):
1 2 3 4 5 6 7 8 9 10
target(copy of values):
1 2 3 4 5 6 7 8 9 10

Using memmove() with overlapping ranges:
values -- elements 0-5 copied to 2-7:
1 2 1 2 3 4 5 8 9 10

Using memcpy() to copy double to int:
target -- 5 double into 10 int positions:
0 1072693248 0 1073741824 0 1074266112 0 1074790400 0 1075052544

最后一次memcpy()调用把数据从double数组复制到int数组。这表明memcpy()不知道也不关心数据类型;它只是把一些字节从一个位置复制到另一个位置(例如,可以从结构中复制字节到字符型数组)复制过程中也不进行类型转换。如果使用循环对元素逐个赋值,那么在赋值过程中会将double类型值转换为int类型值。此时,对字节按原样进行复制,然后程序将把数据作为int类型进行解释。

© 著作权归作者所有

idreamo
粉丝 18
博文 139
码字总数 224743
作品 0
青岛
产品经理
私信 提问
c memmove和memcpy的实现和区别

memcpy和memmove()都是C语言中的库函数,在头文件string.h中,作用是拷贝一定长度的内存的内容,原型分别如下: void memcpy(void dst, const void src, size_t count); void memmove(void...

元禛慎独
2016/09/29
6
0
memcpy的内存重叠问题

【注】改编自memmove 和 memcpy的区别。原作者如有不爽,请告知! memcpy是C语言中的库函数,在头文件string.h中,作用是拷贝一定长度的内存的内容,原型分别如下: 使用memcpy时,有可能会遇...

zidanzzg
2016/12/27
12
0
atoi,itoa,strcpy, strcmp,strcpy, strcpy_s, memc...

strcpy()、strlen()、memcpy()、memmove()、memset()的实现 strcpy(), 字符串拷贝. char strcpy(char strDest, const char strSrc) { assert((strDest!=NULL) && (strSrc !=NULL)); char add......

AlphaJay
2011/07/25
0
0
memcpy和memmove的区别

memcpy和memmove()都是C语言中的库函数,在头文件string.h中,作用是拷贝一定长度的内存的内容,函数原型如下: void my_memcpy(void dest, const void *src,size_t count) void my_memmov...

I慕蓝
2016/05/07
0
0
memmove() -- 拷贝内存内容

memmove() -- 拷贝内存内容 2007年07月06日 星期五 11:41相关函数: bcopy(), memccpy(), memcpy(), strcpy(), strncpy() 表头文件: #include <string.h> 定义函数: void memmove(void dest,......

小熊猫大暴走
2012/04/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

springmvc 流程

1, 首先用户发现 http 请求 到 服务器 ,进入 到 servlet 容器中,servlet 容器 解析请求,和数据 , 以及 httphandler . 解析完的 请求body 数据流。 2. 进入 用户自定义的 filter 过滤器,...

之渊
42分钟前
1
0
django2.2 用户登录练习完整版(待改善)

主要配置: settings.py配置: #数据库配置import pymysqlpymysql.install_as_MySQLdb()DATABASES = {    'default': {        'ENGINE': 'django.db.backends.mysql',  ......

平头哥-Enjoystudy
今天
2
0
if __name__ == '__main__'

通俗的理解__name__ == '__main__':假如你叫小明.py,在朋友眼中,你是小明(__name__ == '小明');在你自己眼中,你是你自己(__name__ == '__main__')。 if __name__ == '__main__'的意思是......

Nagisa丶夜雨
今天
4
0
Skynet 服务创建流程

Skynet 服务创建流程 根据设计综述 Skynet 是为了让服务器充分利用多核优势,将不同的业务放在独立的执行环境中处理。 Skynet 核心功能是加载一个 C 模块(动态库),模块用数字 id 标识,作...

ylme
今天
4
0
js中为什么你不敢用 “==”

前言 类型转换在各个语言中都存在,而在 JavaScript 中由于缺乏对其的了解而不慎在使用中经常造成bug被人诟病。为了避免某些场景下的意外,甚至推崇直接使用 Strict Equality( === )来代替 ...

JamesView
今天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部