高效的 strcpy 并将指针移动到目标的末尾

Posted

技术标签:

【中文标题】高效的 strcpy 并将指针移动到目标的末尾【英文标题】:Efficient strcpy and move pointer to end of destination 【发布时间】:2021-12-28 21:37:39 【问题描述】:

我需要将一些类似 c 的字符串复制到另一个并移动它的指针。我围绕 strcpy 编写了用于移动目标指针的包装器,我想知道是否有更好的方法来做到这一点。

这就是我现在所做的:

#include <string.h>
#include <stdio.h>

// copy t to *s and move **s pointer to the end
void write_obj(char ** s, char * t) 
     strcpy(*s, t);
     (*s) += strlen(t);


void main()
    char json_str[1024];
    char* json_str_ptr;
    char** s = &json_str_ptr;

    printf("Init:\r%08x\n", *s);

    write_obj(s, "12345678");

    printf("%08x\n", *s);

    write_obj(s, "1234");

    printf("%08x\n", *s);

有没有更好和/或更有效的方法来做到这一点?

如何只复制一个字符一个字符并在循环中递增(*s),直到我到达源数组或目标数组末尾的\0

我现在正在 msvc 编译器上对此进行测试,但代码将针对 STM32 微控制器,这将是非常热门的功能。

【问题讨论】:

【参考方案1】:

如果有更好的方法来做到这一点。

    如果有类似 linux 的例程可用,请使用 *s = stpcpy(*s, t)

    如果编译器有很好的优化,可以使用*s += sprintf(*s, "%s", t);。 (如果长度超过INT_MAX,则失败。)

    各种其他O(n) 方法。 restrict基本上是指s, *s, t的数据指针不重叠。

     void write_obj(char * restrict  * restrict s, 
         const char * restrict t) 
       size_t len = strlen(t);
       memcpy(*s, t, len + 1);
       *s += len;
     
    

使用上述方法(所有 O(n)),返回字符串的 end 指针避免了重复 strcat() 的 Schlemiel the Painter's algorithm 问题 O(n*n)

【讨论】:

1.标记为stm32 - 所以没有 linux 2. GCC(主要用于 stm32 开发)不太好。 godbolt.org/z/dP6hzKK1E 3. strlen + memcpy 在这个目标上的效率低于简单的复制功能。没有适用于 stm32 目标 @0___________ 1. 即使 Linux 没有完全移植到 stm32,stm32 stpcpy() 也可能存在,或者很容易制作一个像样的。 2. 有趣的示例代码。 return dest - 1; 看起来不对劲。我希望return dest;sprintf() 返回不包括'\0'。 3. 带有strcpy() 的简单副本仍然要求strlen() 调用形成len。回复:效率,无论哪种方式都是一样的O(n)。 4. “None works for stm32 target”不清楚。您是否建议 write_obj() 不适用于 stm32? @0___________ 也许我们应该 use char *copyandmove(char * restrict dest, const char * restrict src) return dest + sprintf(dest, "%s", src); 让编译器利用非重叠数据。 您的示例没有显示任何内容。它简单地在主函数中打印一个字符串。 restrict 在这种情况下不会改变任何东西(功能代码)。 sprintfstrlen + memcpy 对于这个目标来说效率不是很高。 godbolt.org/z/qPjocb63b Linux 从未移植到 stm32 uC,因为它们没有足够的资源来运行它(STM32MP 不是 uC - 它们是具有 M4 uC 协处理器的应用处理器)。可能可以将 Linux 移植到 stm32H7 或 stm32l4s9 处理器,因为它们有 1M 和 640kB od SRAM。 (H7 SRAM区域不连续,移植难度较大) 它们还需要额外的非易失性存储,因为它们没有足够的闪存来容纳 Linux 内核。【参考方案2】:
    解析 jsons 通常不需要微优化。 IMO 自己的功能会比 strlen + memcpy 更好(在 stm32F429 上测试)。 memcpy 优化通常最适合较长的复制操作 - json 字符串通常很短。 最好尽可能避免副作用。使用函数返回值而不是双指针。
char *copyandmove(char *dest, const char *src)

    while((*dest++ = *src++));
    return dest - 1;


int main(void)

    char x[100];
    char *s = x;

    s = copyandmove(s, "Hello");
    s = copyandmove(s, "");
    s = copyandmove(s, " World");

    printf("Result: `%s`\n", x);


【讨论】:

以上是关于高效的 strcpy 并将指针移动到目标的末尾的主要内容,如果未能解决你的问题,请参考以下文章

简述C语言标准库函数strcpy功能和格式?

strcpy函数如何使用

快速找到未知长度的单链表的中间结点

C语言 指针二维数组怎么初始化

用数组编写strcpy函数,不用指针

无法在C中使用strcpy从指针数组复制字符串? [复制]