测试一下string.h里定义的几个copy函数
/********************************************************
* ANSI定义的函数
* 将<size>个byte(8 bits)从<pSrc>复制到<pDst>
* 未考虑<pDst>覆盖<pSrc>头部或尾部的情况
* 返回值: 指向<pDst>的指针
*/
void *memcpy(void *pDst, const void *pSrc, size_t size);
/********************************************************
* ANSI定义的函数
* 将<size>个byte(8 bits)从<pSrc>复制到<pDst>
* 考虑了<pDst>覆盖<pSrc>头部或尾部的情况
* 返回值: 指向<pDst>的指针
*/
void *memmove(void *pDst, const void *pSrc, size_t size);
ANSI对memcpy()和memmove()的定义略有区别。不过,在VxWorks里,它俩是一模一样的,因为都是用bcopy()实现的
/********************************************************************
* 尽可能使用最高效的方式, 将<size>个byte(8 bits)从<pSrc>复制到<pDst>
* 当<pSrc>和<pDst>都是long对齐时,通常复制速度最快
* 考虑了<pDst>覆盖<pSrc>头部或尾部的情况
*/
void bcopy(const char *pSrc, char *pDst, size_t size);
bcopy()涵盖了<pDst与<pSrc>在头部或尾部有重叠的情况,仅仅忽略了头尾都有重叠的情况,因为太罕见了,得不偿失
/*
* 0 WRAP
* | |
* S-------------------------->|
* D-----------
* -------------->|
*/
写个例子
/*
* 版权所有 公众号 VxWorks567
*/
#include <stdio.h>
#include <string.h>
void test()
{
char *src = "helloworld";
char dst[11];
printf("src = %s\n", src);
/* 正常操作 */
memcpy(dst, src, 10);
dst[10] = 0;
printf("dst = %s\n", dst);
/* 覆盖src的头部 */
memcpy(dst, dst+3, 7);
dst[7] = 0;
printf("dst = %s\n", dst);
/* 覆盖src的尾部 */
memcpy(dst+3, dst, 7);
dst[10] = 0;
printf("dst = %s\n", dst);
}
既然是memory操作,那就有风险,下面列举几个
另外,bcopy()会根据<size>的取值,自动选择最高效的方式进行复制,即使用32-bit或64-bit进行copy。
VxWorks还提供了以下几个函数,让User自行选择合适的机制
/***************************************************
* 将<size>个byte(8 bits)从<pSrc>复制到<pDst>
*
* 适用于memory设备只支持byte指令访问
*/
void bcopyBytes(char *pSrc, char *pDst, size_t size);
/***************************************************
* 将<size>个word(16 bits)从<pSrc>复制到<pDst>
*
* 适用于memory设备只支持word指令访问
* <pSrc>和<pDst>必须是word对齐
*/
void bcopyWords(char *pSrc, char *pDst, size_t size);
/***************************************************
* 将<size>个long word(32 bits)从<pSrc>复制到<pDst>
*
* 适用于memory设备只支持32-bit指令访问
* <pSrc>和<pDst>必须是4-byte对齐
*/
void bcopyLongs(char *pSrc, char *pDst, size_t size);
/****************************************************
* 将<size>个quad word(64 bits)从<pSrc>复制到<pDst>
*
* 适用于memory设备只支持64-bit指令访问
* <pSrc>和<pDst>必须是8-byte对齐
*/
void bcopyQuads(char *pSrc, char *pDst, size_t size);
ANSI还定义了strcpy(),用于复制字符串
/*******************************************
* ANSI定义的函数
* 将string <pSrc>复制到<pDst>, 以'\0'结尾
* 返回值: 指向<pDst>的指针
*/
char *strcpy(char *pDst, const char *pSrc);
strcpy()是以src结尾处的0字符结束,因此,存在越界的风险
/*
* 版权所有 公众号 VxWorks567
*/
#include <stdio.h>
#include <string.h>
int test1()
{
/* dst为NULL */
strcpy(NULL, "hello");
return 0;
}
int test2()
{
char dst[8];
/* src为NULL */
strcpy(dst, NULL);
printf("dst = %s\n", dst);
return 0;
}
int test3()
{
char src[8];
char dst[10];
/* src尾部不带0, 导致越界 */
memset(src,'a',8);
strcpy(dst, src);
printf("dst = %s\n", dst);
return 0;
}
int test4()
{
char dst[8];
/* dst越界 */
strcpy(dst, "helloworld");
printf("dst = %s\n", dst);
return 0;
}
ANSI又定义了strncpy(),相对安全一些了
/*******************************************************
* ANSI定义的函数
* 将<size>个byte(8 bits)从string <pSrc>复制到<pDst>
* 如果<size>大于<pSrc>的长度, 在<pDst>尾部添加'\0'
* 否则, <pDst>的结尾非'\0'
*
* 返回值: 指向<pDst>的指针
*/
char *strncpy(char *pDst, const char *pSrc, size_t size);
不过,风险还是有的
/*
* 版权所有 公众号 VxWorks567
*/
#include <stdio.h>
#include <string.h>
int test1()
{
/* dst为NULL */
strncpy(NULL, "hello", 5);
return 0;
}
int test2()
{
char dst[8];
/* src为NULL */
strncpy(dst, NULL, 5);
return 0;
}
int test3()
{
char src[8];
char dst[10];
/* src尾部不带0, 导致越界 */
memset(src,'a',8);
strncpy(dst, src, 10);
printf("dst = %s\n", dst);
return 0;
}
int test4()
{
char dst[8];
/* dst越界 */
strncpy(dst, "helloworld", 10);
printf("dst = %s\n", dst);
return 0;
}
VxWorks定义了一个再安全一点的strlcpy(),它保证dst的尾部有0结尾
/*********************************************************
* 安全版的strncpy()
* 将至多<size-1>个byte(8 bits)从string <pSrc>复制到<pDst>
* 在<pDst>尾部添加'\0'
*
* 返回值: pSrc的字符数. 如果不小于size, 表示没有全部复制
*/
size_t strlcpy(char *pDst, const char *pSrc, size_t size);
另外,ANSI还定义了sprintf()和snprintf()。功能类似于strcpy(),但它们底层也是用bcopy()封装的
/************************************************
* ANSI定义的函数
* 将格式化的string写入<buffer>, 以'\0'结尾
*
* 返回值: 写入<buffer>的字节数, 不包含结尾的'\0'
*/
int sprintf(char *buffer, const char *fmt, ...);
/***********************************************************
* ANSI定义的函数
* 将长度不超过<size>的格式化的string写入<buffer>, 以'\0'结尾
* <size>包含了结尾的'\0'
*
* 返回值: 写入<buffer>的字节数, 不包含结尾的'\0'
*/
int snprintf(char *buffer, size_t size, const char *fmt, ...);