第16章 C预处理器和C库 16.12 string.h库中的memcpy()、memmove()
2017-07-31 00:00
337 查看
不能把一个数组的值直接赋给另一个数组,因此,我们使用循环把数组中的元素逐个复制到另一个数组。
一个例外情况是:可以使用strcpy()和strncpy()函数复制字符数组。memcpy()和memmove()函数为复制其他类型的数组提供了类似的便利工具。下面是这两个函数的原型:
这两个函数均从s2指向的位置复制n字节数据到s1指向的位置,且均返回s1的值。两者间的区别由关键字restrict造成,即memcpy()可以假定两个内存之间没有重叠。memmove()则不作这个假定,因此,复制过程类似于先将所有字节复制到一个临时缓冲区,然后再复制到最终目的地。如果两个区域存在重叠时使用memcpy()会怎么样呢?其行为是不可预知的,即可能正常工作也可能失败。在不应该使用memcpy()时,编译器不会禁止使用memcpy()。因此,使用memcpy()时,您必须确保没有重叠区域。这是程序员的任务的一部分。
这两个函数可对任何数据类型进行操作,因此两个指针参数为void类型指针。接受各种类型指针导致函数无法知道要复制的数据类型。因此,这两个函数使用第三个参数来指定要复制的字节数。注意,对数组而言,字节数一般不等于元素个数。因此,如果复制10个double类型值组成的数组,那么应使用10*sizeof(double)作为第三个参数,而不是10.
程序清单16.17显示了一些使用这两个函数的示例。
程序清单16.17 mems.c程序
输出如下:
最后一次memcpy()调用把数据从double数组复制到int数组。这表明memcpy()不知道也不关心数据类型;它只是把一些字节从一个位置复制到另一个位置(例如,可以从结构中复制字节到字符型数组)。复制过程中也不进行类型转换。如果使用循环对元素逐个赋值,那么在赋值过程中会将double类型值转换为int类型值。此时,对字节按原样进行复制,然后程序将把数据作为int类型进行解释。
一个例外情况是:可以使用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类型进行解释。
相关文章推荐
- 重写string.h中的字符串操作函数--memmove、memcpy
- C Primer Plus学习 五十七 string.h库中的 memcpy ( )和 memmove ()
- 重写string.h中的字符串操作函数--memmove、memcpy
- 走进C标准库(7)——"string.h"中函数的实现memcmp,memcpy,memmove,memset
- string库之模拟实现memcpy与memmove
- strcpy()、memcpy()、memmove()、memset()的实现
- memcpy和memmove的区别与实现
- memcpy与memmove
- strcpy、memcpy、memmove的区别及实现
- memcpy和memmove的区别??(zhuan)
- 迅雷面试题:memcpy和memmove的区别
- 细谈C语言中的strcpy,strncpy,memcpy,memmove,memset函数
- 实现memcpy、memcpy的优化、memmove、memset、strcpy、strncpy
- 模拟实现strcmp、strstr、memcpy、memmove
- memset ,memcpy ,memmove,strcpy 的根本区别 与实现
- Linux内核中memcpy和memmove函数的区别和实现
- memmove、memcpy和memccpy 对比
- 使用memset、memcpy等函数需要包含string.h而不是strings.h
- memcpy和memmove的区别
- memcpy、memmove、memset及strcpy函数实现和理解