strncopy copying more than n characters
I'm given a shell of a program and have to fill in a few functions.
I have two structs I am given that are automatically created and passed to the functions I must define.
typedef struct {
char data[20];
} msg;
typedef struct {
int seqnum;
int acknum;
int checksum;
char payload[20];
} pkt;
Say I have to define this function foo
and have created it as such:
void foo(msg message) {
printf("%s\n", message.data);
}
When that function is called, it prints out ddddddddddddddddddddôÑ@<úHn½*Ìå«*¤ú¤F«*
. Unless I am incorrect, shouldn't it only be able to hold 20 characters? I am not actually creating msg
.
It gets even stranger if I copy msg.data
to pkt.payload
.
void foo(msg message) {
pkt packet;
strncpy(packet.payload, message.data, sizeof(packet.payload));
printf("%s\n", message.data);
printf("%s\n", packet.payload);
}
message.data prints out the same as before, but packe开发者_开发知识库t.payload prints out eeeeeeeeeeeeeeeeeeee<úeeeeeeeeeeeeeeeeeeee²+!@<úHn½*Ìå«*¤ú¤F«*
. Why is it more than 20 characters?
This is my first time using C so forgive me if this is obvious but I can't even get to the core of the assignment since I'm having trouble with the language.
printf(), with a %s specifier, assumes you are sending it a zero-terminated string. So it reads bytes in memory until it finds a zero (or '\0'
).
strncpy does not append a zero to your destination string unless a zero is encountered in the source string before n characters are reached (at which point the rest of the destination string is padded with zeros, which of course causes it to be zero-terminated).
strncpy
does not terminate the string being copied.
You either have to manually terminate the field,
strncpy(packet.payload, message.data, sizeof(packet.payload) - 1);
packet.payload[sizeof(packet.payload) - 1] = '\0';
printf("%s\n", message.data);
printf("%s\n", packet.payload);
or treat it as a fixed-size potentially unterminated string:
strncpy(packet.payload, message.data, sizeof(packet.payload));
printf("%s\n", message.data);
printf("%.*s\n", sizeof packet.payload, packet.payload);
Alternatively, you may keep it terminated with snprintf
(C99), which is less error-prone, as it always terminates the string.
snprintf(packet.payload, sizeof packet.payload, "%s", message.data);
printf("%s\n", message.data);
printf("%s\n", packet.payload);
strncpy(packet.payload, message.data, sizeof(packet.payload));
packet.payload[sizeof(packet.payload) - 1] = 0;
精彩评论