简体   繁体   中英

Char array memory allocation

I would like to know how the result of the memcpy() with respect to the memory allocation.

#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;
}

With respect to the code , how do we print out the character array in the structure transrules ?

PS : Yes this code throws an error, sheesh char 's !

As the array defined is of type char why does arr [1] still accept an integer value with memcpy() ?

memcpy does not allocate any memory. In your memcpy call, the memory for the destination arr was allocated when the variable arr was defined ( char arr[400] ).

There's a problem there, which is that you haven't allocated enough room. You copy sizeof(updata) bytes into arr , which is probably 1+4+7*256=1797 (this may vary depending on sizeof(int) and on whether __packed__ actually leaves out all unused bytes on your platform). If you really need arr (you probably don't), make it at least sizeof(updata) large. Defining it with char arr[sizeof(updata)] is fine.

If the layout of the structure is defined by some external format, you should use a fixed-size type instead of int (which is 2 or 4 bytes depending on the platform, and could be other sizes but you're unlikely to encounter them).

If the layout of the structure is defined by some external binary format and you want to print out the 1797 bytes in this format, use fwrite .

fwrite(updata, sizeof(updata), 1, stdout);

If you want to have a human representation of the data, use printf with appropriate format specifications.

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);
}

Despite the name, char is in fact the type of bytes. There is no separate type for characters in C. A character constant like 'a' is in fact an integer value (97 on almost all systems, as per ASCII ). It's things like writing it with putchar or printf("%c", …) that make the byte interpreted as a character.

If your compiler is not signaling an error when you mix up a pointer (such as char* ) with an integer, on the other hand, turn up the warning level. With Gcc, use at least gcc -O -Wall .


After actually compiling your code, I see the main error (you should have copy-pasted the error message from the compiler in your question):

udpdata.rules[0].myname = "lalla\0" ;

udpdata.rules[0].myname is an array of bytes. You can't assign to an array in C. You need to copy the elements one by one. Since this is an array of char , and you want to copy a string into it, you can use strcpy to copy all the bytes of the string. For a bunch of bytes in general, you would use memcpy .

strcpy(udpdata.rules[0].myname, "lalla");

(Note that "lalla\\0" is equivalent to "lalla" , all string literals are zero-terminated in C.¹) Since strcpy does not perform any size verification, you must make sure that the string (including its final null character) fits in the memory that you've allocated for the targets. You can use other functions such as strncat or strlcpy if you want to specify a maximum size.

¹ There's one exception (and only this exception) where "lalla" won't be zero-terminated: when initializing an array of 5 bytes, eg char bytes[5] = "lalla" . If the array size is at least 6 or unspecified, there will be a terminating zero byte.

// 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));

Concerning printing, I don't know how big ints are on your machine but if they are 4 bytes then

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

I'm not sure why you want to convert everything to a char array if you wanted to print out the content. Just use the struct and a for loop. Anyway I think you may want to read up on C arrays.

With respect to the code , how do we print out the character array in the structure transrules ?

/* incorrect -> udpdata.rules[0].myname = "lalla\0" ; */
strcpy(udpdata.rules[0].myname,"lalla") ;
printf("%s\n",udpdata.rules[0].myname);

As the array defined is of type char why does arr [1] still accept an integer value with memcpy ?

memcpy doesn't know or care about what the underlying datatypes might be where it is copying to. It takes void pointers and copies the value in one or more byte to one or more other bytes:

void * memcpy ( void * destination, const void * source, size_t num );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM