Reputation: 410
According to man 3 memccpy
the memccpy
function is defined as follows:
SYNOPSIS
#include <string.h> void *memccpy(void *dest, const void *src, int c, size_t n);
DESCRIPTION
The
memccpy()
function copies no more thann
bytes from memory areasrc
to memory areadest
, stopping when the characterc
is found.If the memory areas overlap, the results are undefined.
What confuses me is that memccpy
copies n
bytes and stops if character c
is found. However, the function takes int c
as an argument. So what happens if I call memccpy
with the following value:
memccpy(&x, &y, 0xffffff76, 100);
Here the value to check is too big for char
. Should this case work?
Upvotes: 3
Views: 779
Reputation: 69512
memccpy()
is defined by POSIX.1-2001 (IEEE Std 1003.1-2001), which states:
SYNOPSIS
#include <string.h> void *memccpy(void *restrict s1, const void *restrict s2, int c, size_t n);
DESCRIPTION
The
memccpy()
function shall copy bytes from memory areas2
intos1
, stopping after the first occurrence of bytec
(converted to an unsigned char) is copied, or after n bytes are copied, whichever comes first. If copying takes place between objects that overlap, the behavior is undefined.
So there you go, a simple unsigned char
conversion takes place:
void *memccpy(void *restrict s1, const void *restrict s2, int c, size_t n) {
unsigned char actual_c = (unsigned char)c;
// ...
}
In fact, the most prominent C standard library implementations that I know do exactly this:
memchr
which does unsigned char c = (unsigned int)c_in;
unsigned char uc = c;
unsigned char uc = c;
c = (unsigned char)c;
(((unsigned char)(*r1++ = *r2++)) != ((unsigned char) c))
Upvotes: 6
Reputation: 225767
This is an older function which is similar to memset
in terms of the argument it accepts:
void *memset(void *s, int c, size_t n);
It is described in the C standard as follows:
The
memset
function copies the value ofc
(converted to anunsigned char
) into each of the firstn
characters of the object pointed to bys
.
Both functions date back to at least 4.3 BSD, so it would make sense that they handle their arguments in a similar way.
So given your example, the value 0xffffff76 would be converted to the unsigned char
value 0x76, and that would be the value it check for to stop.
Upvotes: 1
Reputation: 142005
how exactly this case is handled in code
Just the value of the parameter is converted to a character:
void *memccpy(..., int param_c, ...) {
unsigned char c = param_c;
In real life : https://github.com/lattera/glibc/blob/master/string/memccpy.c#L33 https://github.com/lattera/glibc/blob/master/string/memchr.c#L63 .
(On nowadays systems) unsigned char
has 8 bits, (unsigned char)(int)0xffffff76
just becomes 0x76
. The upper bits are just ignored.
Upvotes: 4