前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >几个copy函数

几个copy函数

作者头像
Taishan3721
发布2023-02-20 16:19:38
9070
发布2023-02-20 16:19:38
举报
文章被收录于专栏:这里只有VxWorks这里只有VxWorks

测试一下string.h里定义的几个copy函数

代码语言:javascript
复制
/********************************************************
 * 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()实现的

代码语言:javascript
复制
/********************************************************************
 * 尽可能使用最高效的方式, 将<size>个byte(8 bits)从<pSrc>复制到<pDst>
 * 当<pSrc>和<pDst>都是long对齐时,通常复制速度最快
 * 考虑了<pDst>覆盖<pSrc>头部或尾部的情况
 */
void bcopy(const char *pSrc, char *pDst, size_t size);

bcopy()涵盖了<pDst与<pSrc>在头部或尾部有重叠的情况,仅仅忽略了头尾都有重叠的情况,因为太罕见了,得不偿失

代码语言:javascript
复制
/*
 *   0                                         WRAP
 *   |                                         |
 *         S-------------------------->|
 *                                 D-----------
 *   -------------->|
 */

写个例子

代码语言:javascript
复制
/*
 * 版权所有  公众号  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自行选择合适的机制

代码语言:javascript
复制
/***************************************************
 * 将<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(),用于复制字符串

代码语言:javascript
复制
/*******************************************
 * ANSI定义的函数
 * 将string <pSrc>复制到<pDst>, 以'\0'结尾
 * 返回值: 指向<pDst>的指针
 */
char *strcpy(char *pDst, const char *pSrc);

strcpy()是以src结尾处的0字符结束,因此,存在越界的风险

代码语言:javascript
复制
/*
 * 版权所有  公众号  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(),相对安全一些了

代码语言:javascript
复制
/*******************************************************
 * 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);

不过,风险还是有的

代码语言:javascript
复制
/*
 * 版权所有  公众号  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结尾

代码语言:javascript
复制
/*********************************************************
 * 安全版的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()封装的

代码语言:javascript
复制
/************************************************
 * 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, ...);
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-01-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 这里只有VxWorks 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档