Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

memcpy for copying a fixed length buffer into a structure

Tags:

c

I have this sample code:

struct
{
    char a[2];
    char b[2];
} buff;

char buffer1[5] = "ABCD";

To copy the buffer1 to structure members, I am doing like this:

char c[3],d[3];
memcpy(&buff,buffer1,4);
sprintf(c,"%2.2s",buff.a);
sprintf(d,"%2.2s",buff.b);
printf("c=%s,d=%s",c,d);

When I print the variables c and d, I am getting the values in c and d variable properly as: c="AB" and c="CD".

Well my question is, even though I am getting the output properly, will memcpy affect anything related to null character termination or have other unexpected memory-related consequences?

like image 467
Gajendra Bagali Avatar asked Jun 19 '15 11:06

Gajendra Bagali


People also ask

How does the memcpy () function work?

The memcpy () built-in function copies count bytes from the object pointed to by src to the object pointed to by dest. See Built-in functions for information about the use of built-in functions.

What is the difference between memcpy () and memmove () in C?

memcpy () is used to copy a block of memory from a location to another. It is declared in string.h Below is a sample C program to show working of memcpy (). 2) memcpy () leads to problems when source and destination addresses overlap. memmove () is another library function that handles overlapping well. Writing code in comment?

What is the difference between memcpy () and SRC ()?

Following is the declaration for memcpy () function. dest − This is pointer to the destination array where the content is to be copied, type-casted to a pointer of type void*. src − This is pointer to the source of data to be copied, type-casted to a pointer of type void*.

How do I overlap the source characters in memcpy?

For memcpy (), the source characters may be overlaid if copying takes place between objects that overlap. Use the memmove () function to allow copying between objects that overlap. memcpy () returns the value of dest.


1 Answers

The are two issues here:

1) As mentioned in comments you likely forget to include space for the ending '\0' (i.e. NUL in ASCII) terminator character. The %s format specifier for printf function expects that character string is in valid form. However nothing stops you from printing as sequence of characters, like here:

#include <stdio.h>
#include <string.h>

struct {
    char a[2];
    char b[2];
} buff;

char buffer1[5] = "ABCD";

int main(void)
{
    memcpy(&buff, buffer1, 4);

    printf("First member: %c%c\n", buff.a[0], buff.a[1]);
    printf("Second member: %c%c\n", buff.b[0], buff.b[1]);

    return 0;
}

2) A more serious issue is that compiler may include arbitrary padding between struct members (as well as after last member), so memcpy may not work as expected. Instead of copying like that (as it may put bytes from array into a unused "wholes"). I would suggest individual copies of each member or maybe using offsetof() macro.

From N1570 6.7.2.1/15 Structure and union specifiers:

There may be unnamed padding within a structure object, but not at its beginning.

and 6.7.2.1/17:

There may be unnamed padding at the end of a structure or union.

Hence, you should split your memcpy into two calls, for instance:

memcpy(&buff.a, buffer1, 2); /* or replace 2 with sizeof buff.a */
memcpy(&buff.b, buffer1+2, 2);
like image 127
Grzegorz Szpetkowski Avatar answered Oct 13 '22 00:10

Grzegorz Szpetkowski