我想知道memcpy()
关于内存分配的结果。
#include<stdio.h>
#include<string.h>
typedef struct {
char myname[7] ;
} transrules;
trans typedef struct {
char ip ;
int udp;
transrules rules[256];
} __attribute__ ((__packed__)) myudp;
myudp __attribute__ ((__packed__)) udpdata ;
char arr[400] ;
int main() {
memset (&udpdata , 0 ,sizeof(udpdata));
udpdata.ip = 'a' ;
udpdata.udp = 13 ;
udpdata.rules[0].myname = "lalla\0" ;
memcpy (&arr , &udpdata, sizeof(udpdata));
printf("%c",arr[0]);
return 0;
}
关于代码,我们如何打印结构transrules
中的字符数组?
PS:是的,这段代码会抛出一个错误,谢谢char
的!
由于定义的数组类型为char
,为什么arr [1]仍接受memcpy()
的整数值?
答案 0 :(得分:3)
memcpy
不分配任何内存。在memcpy
调用中,在定义变量arr
(arr
)时分配了目标char arr[400]
的内存。
那里有一个问题,那就是你没有分配足够的空间。您将sizeof(updata)
个字节复制到arr
,这可能是1 + 4 + 7 * 256 = 1797(这可能会因sizeof(int)
而异,以及__packed__
是否实际上全部废弃了平台上未使用的字节)。如果你真的需要arr
(你可能不需要),那么至少要sizeof(updata)
大。{用char arr[sizeof(updata)]
定义它很好。
如果结构的布局是由某种外部格式定义的,则应使用固定大小的类型而不是int
(根据平台,这是2或4个字节,可能是其他大小,但是你“不太可能遇到它们。”
如果结构的布局是由某种外部二进制格式定义的,并且您希望以此格式打印出1797字节,请使用fwrite
。
fwrite(updata, sizeof(updata), 1, stdout);
如果您想拥有数据的人工代表,请使用具有相应格式规范的printf
。
printf("ip='%c' udp=%d\n", updata.ip, updata.ip);
for (i = 0; i < sizeof(updata.rules)/sizeof(updata.rules[0]); i++) {
puts(updata.rules[i].myname);
}
尽管有名称,char
实际上是字节的类型。 C中的字符没有单独的类型。像'a'
这样的字符常量实际上是一个整数值(几乎所有系统都是97,按照ASCII)。这就像用putchar
或printf("%c", …)
编写它,使字节被解释为一个字符。
如果在将指针(例如char*
)与整数混淆时编译器没有发出错误信号,则调高警告级别。使用Gcc,至少使用gcc -O -Wall
。
在实际编译代码之后,我看到了主要错误(您应该在问题中复制粘贴编译器中的错误消息):
udpdata.rules[0].myname = "lalla\0" ;
udpdata.rules[0].myname
是一个字节数组。您无法在C中分配数组。您需要逐个复制元素。由于这是char
的数组,并且您希望将字符串复制到其中,因此可以使用strcpy
复制字符串的所有字节。对于一般的一堆字节,您可以使用memcpy
。
strcpy(udpdata.rules[0].myname, "lalla");
(请注意,"lalla\0"
相当于"lalla"
,所有字符串文字都在C中以零结尾.¹)由于strcpy
不执行任何大小验证,您必须确保字符串(包括其最终的空字符)适合您为目标分配的内存。如果要指定最大尺寸,可以使用其他功能,例如strncat
或strlcpy
。
¹有一个例外(并且只有这个例外),其中"lalla"
不会被零终止:当初始化一个5字节的数组时,例如char bytes[5] = "lalla"
。如果数组大小至少为6或未指定,则会有一个终止零字节。
答案 1 :(得分:1)
// this is really bad udpdata.rules[0].myname = "lalla\0" ; // do this instead. You want the literal string in your field. memcpy(udpdata.rules[0].myname, "lalla\0", 6); .... // This is wrong. arr is already a pointer. memcpy (&arr , &udpdata, sizeof(udpdata)); // do this instead mempcy (arr, &udpdata, sizeof(udpdate));
关于打印,我不知道您的计算机有多大的整数,但如果它们是4字节,那么
printf("%.7s", &arr[1+4]);
如果您想打印内容,我不确定为什么要将所有内容转换为char数组。只需使用struct和 for 循环即可。无论如何,我想你可能想要阅读C数组。
答案 2 :(得分:1)
关于代码,我们如何在结构规则中打印字符数组?
/* incorrect -> udpdata.rules[0].myname = "lalla\0" ; */
strcpy(udpdata.rules[0].myname,"lalla") ;
printf("%s\n",udpdata.rules[0].myname);
由于定义的数组是char类型,为什么arr [1]仍然接受带memcpy的整数值?
memcpy不知道或不关心它复制到的基础数据类型。它接受void指针并将一个或多个字节中的值复制到一个或多个其他字节:
void * memcpy ( void * destination, const void * source, size_t num );