非常教程

C参考手册

字符串 | Strings

memcpy_s

在头文件<string.h>中定义

(1)

void * memcpy(void * dest,const void * src,size_t count);

(直到C99)

void * memcpy(void * restrict dest,const void * restrict src,size_t count);

(自C99以来)

errno_t memcpy_s(void * restrict dest,rsize_t destsz,const void * restrict src,rsize_t count);

(2)

(自C11以来)

1)复制src指向的对象中的字符到dest指向的对象。 两个对象都被解释为无符号字符数组。

如果访问超出dest数组的末尾,则行为未定义。 如果对象重叠(这违反了限制合同)(自C99以来),行为未定义。 如果dest或src是空指针,则行为是未定义的。

2)与(1)相同,只是在运行时检测到以下错误并导致整个目标范围[dest,dest + destsz)被清零(如果dest和destsz都有效),并且调用当前 安装约束处理函数:

  • dest或者src是空指针
  • destszcount大于RSIZE_MAX
  • count大于destsz(会发生缓冲区溢出)
  • 源和目标对象重叠

如果由dest <count <= destsz指向的字符数组的大小,行为是未定义的; 换句话说,destsz的错误值不会暴露即将发生的缓冲区溢出。 作为所有边界检查的函数,只有当__STDC_LIB_EXT1__由实现定义并且用户在包含string.h之前将__STDC_WANT_LIB_EXT1__定义为整数常量1时,memcpy_s才能保证可用。

参数

dest

-

指向要复制到的对象的指针

destsz

-

在目标中修改的最大字节数(通常是目标对象的大小)

src

-

指向要从中复制的对象的指针

count

-

要复制的字节数

返回值

1)返回一份 dest 副本

2)成功时返回零,错误时返回非零值。 同样出错的是,如果dest不是空指针且destsz有效,则将destsz零字节写入目标数组。

注意

memcpy 可用于设置由分配函数获得的对象的有效类型。

memcpy是内存到内存拷贝速度最快的库例程。 它通常比strcpy更高效,它必须扫描它拷贝或移除的数据,这必须采取预防措施来处理重叠输入。

几个C编译器将合适的内存复制循环转换为memcpy调用。

在严格别名禁止检查与两种不同类型的值相同的内存的情况下,memcpy可以用来转换这些值。

#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
#include <stdlib.h>
 
int main(void)
{
    // simple usage
    char source[] = "once upon a midnight dreary...", dest[4];
    memcpy(dest, source, sizeof dest);
    for(size_t n = 0; n < sizeof dest; ++n)
        putchar(dest[n]);
 
    // setting effective type of allocated memory to be int
    int *p = malloc(3*sizeof(int));   // allocated memory has no effective type
    int arr[3] = {1,2,3};
    memcpy(p,arr,3*sizeof(int));      // allocated memory now has an effective type
 
    // reinterpreting data
    double d = 0.1;
//    int64_t n = *(int64_t*)(&d); // strict aliasing violation
    int64_t n;
    memcpy(&n, &d, sizeof d); // OK
    printf("\n%a is %" PRIx64 " as an int64_t\n", d, n);
 
#ifdef __STDC_LIB_EXT1__
    set_constraint_handler_s(ignore_handler_s);
    char src[] = "aaaaaaaaaa";
    char dst[] = "xyxyxyxyxy";
    int r = memcpy_s(dst,sizeof dst,src,5);
    printf("dst = \"%s\", r = %d\n", dst,r);
    r = memcpy_s(dst,5,src,10);            //  count is greater than destsz  
    printf("dst = \"");
    for(size_t ndx=0; ndx<sizeof dst; ++ndx) {
        char c = dst[ndx];
        c ? printf("%c", c) : printf("\\0");
    }
    printf("\", r = %d\n", r);
#endif
}

可能的输出:

once
0x1.999999999999ap-4 is 3fb999999999999a as an int64_t
dst = "aaaaayxyxy", r = 0
dst = "\0\0\0\0\0yxyxy", r = 22

参考

  • C11标准(ISO / IEC 9899:2011):
    • 7.24.2.1 memcpy函数(p:362)
    • K.3.7.1.1 memcpy_s函数(p:614)
  • C99标准(ISO / IEC 9899:1999):
    • 7.21.2.1 memcpy函数(p:325)
  • C89 / C90标准(ISO / IEC 9899:1990):
    • 4.11.2.1 memcpy函数

扩展内容

memmovememmove_s(C11)

移动一个缓冲区到另一个(功能)

wmemcpywmemcpy_s(C95)(C11)

在两个非重叠数组之间复制一定数量的宽字符(函数)

| 用于memcpy的C ++文档 |

C

C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。