Reputation: 177
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?
Upvotes: 5
Views: 11986
Reputation: 73366
buffer1
is null terminated. However, the data members of buff
are not, since you don't append a null terminator on them. Moreover, you don't have space for the null terminator!
So, no it won't affect it, since it's not there. You will get unexpected results when you try to use the functions of stdio.h
, which expect a null terminated string.
Also, you might want to check my example here, about looping in a struct, that it's somehow relevant. I would suggest you to copy to one data member at a time and not in one go.
Upvotes: 1
Reputation: 37914
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);
Upvotes: 7
Reputation: 12263
That might not work as expected. There might be padding bytes between the fields in a structure. These are inserted between fields to have the next field start at a certain address-offset. This is mostly the word-size of the CPU or the bus-size, or a multiple thereof for cache-alignment.
This can be true even for char []
, as that would allow to efficiently moves/copy such arrays using word-transfers.
For other types, padding is very likely and additionally you have to care about endianess.
Remember also that memcpy
& friends exactly do what their names imply: they operate on a block of memory. The do not care about strings, they do not have an idea about "strings". Inserting any NUL-bytes would render them useless, so they don't.
Note that this approach is similar to casting incompatible pointer types. There are few places you are safe, but most times this is the road to hell (aka undefined behaviour).
Upvotes: 1
Reputation: 441
#include<stdio.h>
#include<string.h>
struct
{
char a[2];
char b[2];
}buff;
int main ( void )
{
char buffer1[4] = "ABCD";
memcpy ( &buff , buffer1 , 4 );
printf ( "\n%s\n ", buff.a );
printf ( "\n%s\n ", buff.b );
return ( 0 );
}
o/p-->
rabi@rabi-VirtualBox:~/rabi/c$ gcc 16.c
rabi@rabi-VirtualBox:~/rabi/c$ ./a.out
ABCD
CD
rabi@rabi-VirtualBox:~/rabi/c$
#include<stdio.h>
#include<string.h>
struct
{
char a[3];
char b[3];
}buff;
int main ( void )
{
char buffer1[4] = "ABCD";
memcpy ( &buff.a , &buffer1[0], 2 );
buff.a[2]='\0';
memcpy ( &buff.b , &buffer1[2], 2 );
buff.b[2]='\0';
printf ( "\n%s\n ", buff.a );
printf ( "\n%s\n ", buff.b );
return ( 0 );
}
o/p--->
rabi@rabi-VirtualBox:~/rabi/c$ gcc 15.c
rabi@rabi-VirtualBox:~/rabi/c$ ./a.out
AB
CD
rabi@rabi-VirtualBox:~/rabi/c$
Upvotes: -1