用于将固定长度缓冲区复制到结构中的memcpy

Gaj*_*ali 4 c

我有这个示例代码:

struct
{
    char a[2];
    char b[2];
} buff;

char buffer1[5] = "ABCD";
Run Code Online (Sandbox Code Playgroud)

要复制buffer1到结构成员,我这样做:

char c[3],d[3];
memcpy(&buff,buffer1,4);
sprintf(c,"%2.2s",buff.a);
sprintf(d,"%2.2s",buff.b);
printf("c=%s,d=%s",c,d);
Run Code Online (Sandbox Code Playgroud)

当我打印变量c和d时,我正确地将c和d变量中的值变为:c="AB"c="CD".

那么我的问题是,即使我正确地获得输出,也会memcpy影响与空字符终止相关的任何事情或者有其他意外的与记忆相关的后果吗?

Grz*_*ski 7

这里有两个问题:

1)如评论中所述,您可能忘记在结尾'\0'(即NULASCII)终结符字符中包含空格.函数的%s格式说明printf符要求字符串的格式有效.然而,没有什么能阻止你打印成字符序列,就像这里:

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

struct {
    char a[2];
    char b[2];
} buff;

char buffer1[5] = "ABCD";

int main(void)
{
    memcpy(&buff, buffer1, 4);

    printf("First member: %c%c\n", buff.a[0], buff.a[1]);
    printf("Second member: %c%c\n", buff.b[0], buff.b[1]);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

2)更严重的问题是编译器可能在结构成员之间(以及在最后一个成员之后)包含任意填充,因此memcpy可能无法按预期工作.而不是像那样复制(因为它可能将数组中的字节放入未使用的"整体").我会建议每个成员的个人副本或使用offsetof()宏.

从N1570 6.7.2.1/15 结构和联合说明符:

结构对象中可能存在未命名的填充,但不是在其开头.

并且6.7.2.1/17:

结构或联合的末尾可能有未命名的填充.

因此,您应该将您memcpy分成两个调用,例如:

memcpy(&buff.a, buffer1, 2); /* or replace 2 with sizeof buff.a */
memcpy(&buff.b, buffer1+2, 2);
Run Code Online (Sandbox Code Playgroud)