【问题标题】:Difference in memcpy and strncpy for struct copying用于结构复制的 memcpy 和 strncpy 的区别
【发布时间】:2014-12-01 19:10:12
【问题描述】:

我有以下代码。我正在尝试将结构复制到字符串。我想了解为什么输出在 strncpy 和 memcpy 之间变化。

#include <stdio.h>
#include<string.h>
struct a{
    int len;
    int type;
};
int main(){
    struct a aa={98,88};
    char str[10]="";
    char str2[10]="";

    strncpy(str,&aa,sizeof(struct a));
    memcpy(str2,&aa,sizeof(struct a));
    for(int i=0;i<10;i++)printf("%2d",str[i]);
    printf("\n");
    for(int i=0;i<10;i++)printf("%2d",str2[i]);

    return 0;
}

下面是输出:

98 0 0 0 0 0 0 0 0 0
98 0 0 088 0 0 0 0 0

我知道 strncpy 将复制直到它达到 '\0'(或大小限制),但我在结构中没有 '\0' 值。有人可以帮我理解这一点。 这样做的目的:尝试通过网络发送一个结构。虽然我打算实现序列化,但我想了解行为

编辑: 1)由基思·汤普森推荐

以下是生成的警告。

incompatible pointer types passing 'struct a *' to parameter of type 'const char *' [-Wincompatible-pointer-types]

2)我稍微修改了代码以使用 int 数组:

(作为参考。我知道在这种情况下,memcpy 将 struct 的变量复制到数组的前两个元素中,因为大小足以容纳 struct 变量。)

#include <stdio.h>
#include<string.h>
struct a{
    int len;
    int type;
};
int main(){
    struct a aa={98,88};
    int str[10]={0};
    int str2[10]={0};

    strncpy(str,&aa,sizeof(struct a));
    memcpy(str2,&aa,sizeof(struct a));
    for(int i=0;i<10;i++)printf("%2d",str[i]);
    printf("\n");
    for(int i=0;i<10;i++)printf("%2d",str2[i]);

    return 0;
}

下面是o\p:

98 0 0 0 0 0 0 0 0 0
9888 0 0 0 0 0 0 0 0

以下是生成的警告:

incompatible pointer types passing 'int [10]' to parameter of type 'char *' [-Wincompatible-pointer-types]
incompatible pointer types passing 'struct a *' to parameter of type 'const char *' [-Wincompatible-pointer-types]

【问题讨论】:

  • 你的结构不是字符串。 strncpy 对字符串进行操作。该调用甚至不应该编译;你至少应该得到一个警告,将struct a* 参数传递给strncpy,它需要char*。即使是字符串,strncpy 通常也应该避免; see my rant on the topic here.
  • 它确实引发了警告。
  • 请更新您的问题以显示确切的警告;这是非常重要的信息。
  • 感谢@KeithThompson 添加了警告。还添加了另一个示例

标签: c struct memcpy strncpy


【解决方案1】:

但我在结构中没有 '\0' 值。

实际上,您确实至少有六个'\0'-s:假设int 是32 位,9888 的高三个字节都是零。他们会让strncpy 停止复制。该函数是为固定长度的字符串设计的,因此不应将其与任意structs 一起使用。另一方面,memcpy 会复制所有内容。

这样做的目的:尝试通过网络发送结构。

如果您想通过网络发送您的struct,并且您希望数据包是可移植的,请在发送方将ints 转换为网络顺序,并在接收方转换回硬件顺序.对于 32 位数字,请使用 htonl and ntohl functions

【讨论】:

  • 谢谢,错过了 '\0' 等于 0.strcpy 将在 0 处停止。
【解决方案2】:

memcpy 复制字节,strcpy 复制以 nul 结尾的字符串(nul 是 0 字节,0x00,'\x00')

memcpy 总是复制指定的字节数。 strcpy 在找到 nul 时停止复制

【讨论】:

    【解决方案3】:

    但我在结构中没有 '\0' 值。

    是的,你知道。您的整数值有 0 位,当字节数据被解释为字符时,它可以被解释为 '\0'。由于strncpy“逐个字符地工作,直到到达终止符”,这会导致它提前停止。

    memcpy 复制指定数量的字节,总是,这使它工作。在这种情况下更合适。

    【讨论】:

    • 谢谢,错过了 '\0' 等于 0
    猜你喜欢
    • 2011-06-03
    • 2014-04-26
    • 2018-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多