1

我想知道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()

4

3 回答 3

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 或未指定,则将有一个终止零字节。

于 2012-09-05T00:07:09.290 回答
1
// 这真的很糟糕
udpdata.rules[0].myname = "lalla\0" ;

// 改为这样做。您希望在您的字段中使用文字字符串。
memcpy(udpdata.rules[0].myname, "lalla\0", 6);

……

// 这是错误的。arr 已经是一个指针。
memcpy (&arr , &udpdata, sizeof(udpdata));

// 改为这样做
mempcy (arr, &udpdata, sizeof(udpdate));

关于打印,我不知道你的机器上有多大的整数,但如果它们是 4 个字节,那么

printf("%.7s", &arr[1+4]);

如果要打印内容,我不确定为什么要将所有内容都转换为 char 数组。只需使用结构和for循环。无论如何,我认为您可能想阅读 C 数组。

于 2012-09-04T23:56:07.290 回答
1

关于代码,我们如何打印出结构体transrules中的字符数组?

/* 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 );
于 2012-09-05T00:08:02.283 回答