Difference in memcpy and strncpy for struct copying

1k views Asked by At

I have the below code. I am trying to copy a struct to a string. I want to understand why the output varies between strncpy and memcpy.

#include <stdio.h>
#include<string.h>
struct a{
    int len;
    int type;
};
int main(){
    struct a aa={98,88};
    char str[10]="";
    char str2[10]="";

    strncpy(str,&aa,sizeof(struct a));
    memcpy(str2,&aa,sizeof(struct a));
    for(int i=0;i<10;i++)printf("%2d",str[i]);
    printf("\n");
    for(int i=0;i<10;i++)printf("%2d",str2[i]);

    return 0;
}

Below is the Output:

98 0 0 0 0 0 0 0 0 0
98 0 0 088 0 0 0 0 0

I understand the strncpy will copy till it hits '\0' (or the size limit), but i don't have '\0' value in the struct. Can someone please help me understand this. Purpose of doing this: trying to send a struct over network. Though I am planning to implement serialization, I wanted to understand the behavior

EDIT: 1)Suggested by Keith Thompson

Below is the warning generated.

incompatible pointer types passing 'struct a *' to parameter of type 'const char *' [-Wincompatible-pointer-types]

2)I modified the code a bit to use int array:

(Putting this for reference. I understand that in this case, memcpy copies the variable of struct in the first two elements of the array as the size is sufficient for the struct variable.)

#include <stdio.h>
#include<string.h>
struct a{
    int len;
    int type;
};
int main(){
    struct a aa={98,88};
    int str[10]={0};
    int str2[10]={0};

    strncpy(str,&aa,sizeof(struct a));
    memcpy(str2,&aa,sizeof(struct a));
    for(int i=0;i<10;i++)printf("%2d",str[i]);
    printf("\n");
    for(int i=0;i<10;i++)printf("%2d",str2[i]);

    return 0;
}

Below is the o\p:

98 0 0 0 0 0 0 0 0 0
9888 0 0 0 0 0 0 0 0

Below are the warnings generated:

incompatible pointer types passing 'int [10]' to parameter of type 'char *' [-Wincompatible-pointer-types]
incompatible pointer types passing 'struct a *' to parameter of type 'const char *' [-Wincompatible-pointer-types]
3

There are 3 answers

1
Sergey Kalinichenko On BEST ANSWER

but I don't have '\0' value in the struct.

Actually, you do have at least six '\0'-s there: assuming that int is 32-bit, the upper three bytes of both 98 and 88 are all zeros. They would make strncpy stop copying. The function is designed for fixed-length strings, so one should not use it with arbitrary structs. memcpy, on the other hand, will copy everything.

Purpose of doing this: trying to send a struct over network.

If you would like to send your struct over the network, and you would like the packet to be portable, convert both ints to network order on the sender side, and back to hardware order on the receiving side. For 32-bit numbers use htonl and ntohl functions.

0
Andras On

memcpy copies bytes, strcpy copies nul-terminated strings (nul is the 0 byte, 0x00, '\x00')

memcpy always copies the specified number of bytes. strcpy stops copying when it finds a nul

1
Reed Copsey On

but i don't have '\0' value in the struct.

Yes, you do. Your integer values have 0 bits, which can be interpreted as a '\0' when the byte data is interpreted as characters. Since strncpy works "character by character until a terminator is reached", this causes it to stop early.

memcpy copies the specified number of bytes, always, which makes it work. It is more appropriate in this case.