您的位置:首页 > 运维架构

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

2017-07-31 00:00 337 查看
不能把一个数组的值直接赋给另一个数组,因此,我们使用循环把数组中的元素逐个复制到另一个数组。

一个例外情况是:可以使用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类型进行解释。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息