字符数组内存分配

时间:2012-09-04 23:33:16

标签: c

我想知道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()的整数值?

3 个答案:

答案 0 :(得分:3)

memcpy不分配任何内存。在memcpy调用中,在定义变量arrarr)时分配了目标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)。这就像用putcharprintf("%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不执行任何大小验证,您必须确保字符串(包括其最终的空字符)适合您为目标分配的内存。如果要指定最大尺寸,可以使用其他功能,例如strncatstrlcpy

¹有一个例外(并且只有这个例外),其中"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 );