Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Is memcpy with len=0 a NOP?

Reply
Thread Tools

Is memcpy with len=0 a NOP?

 
 
Noob
Guest
Posts: n/a
 
      01-24-2011
Hello,

Consider

int i = 123;
int j = 456;
memcpy(&i, &j, 0);

Is the call to memcpy with len==0 well-defined, and equivalent
to a NOP, leaving the entire state machine unchanged?
(i and j unchanged, but everything else too)

I believe memcpy(foo, bar, 0) is indeed equivalent to a NOP.
Please correct me if I'm wrong.

My C89 draft only states

4.11.2.1 The memcpy function

Synopsis

#include <string.h>
void *memcpy(void *s1, const void *s2, size_t n);

Description

The memcpy function copies n characters from the object pointed to
by s2 into the object pointed to by s1 . If copying takes place
between objects that overlap, the behavior is undefined.

Returns

The memcpy function returns the value of s1 .

Regards.
 
Reply With Quote
 
 
 
 
Ben Bacarisse
Guest
Posts: n/a
 
      01-24-2011
Noob <root@127.0.0.1> writes:

> Consider
>
> int i = 123;
> int j = 456;
> memcpy(&i, &j, 0);
>
> Is the call to memcpy with len==0 well-defined, and equivalent
> to a NOP, leaving the entire state machine unchanged?
> (i and j unchanged, but everything else too)


In this case, yes, it's a no-op.

> I believe memcpy(foo, bar, 0) is indeed equivalent to a NOP.
> Please correct me if I'm wrong.


This is not quite a no-op because the call is undefined when either or
both of the pointer arguments are null (see 7.1.4 p1 of C99). It's a
no-op when both pointers are valid, and it is even a well-defined (as a
no-op) when the pointers are the same (where a call with any non-zero
value for the size would be undefined).

I've come across a few (admittedly rare) cases where code would be
simpler if the degenerate case of copying zero bytes to or from a null
pointer were well-defined. I image there is a non-trivial amount of
code "in the wild" that assumes it is well-defined.

<snip>
--
Ben.
 
Reply With Quote
 
 
 
 
Noob
Guest
Posts: n/a
 
      01-24-2011
Ben Bacarisse wrote:

> Noob wrote:
>
>> Consider
>>
>> int i = 123;
>> int j = 456;
>> memcpy(&i,&j, 0);
>>
>> Is the call to memcpy with len==0 well-defined, and equivalent
>> to a NOP, leaving the entire state machine unchanged?
>> (i and j unchanged, but everything else too)

>
> In this case, yes, it's a no-op.
>
>> I believe memcpy(foo, bar, 0) is indeed equivalent to a NOP.
>> Please correct me if I'm wrong.

>
> This is not quite a no-op because the call is undefined when either or
> both of the pointer arguments are null (see 7.1.4 p1 of C99). It's a
> no-op when both pointers are valid, and it is even a well-defined (as a
> no-op) when the pointers are the same (where a call with any non-zero
> value for the size would be undefined).
>
> I've come across a few (admittedly rare) cases where code would be
> simpler if the degenerate case of copying zero bytes to or from a null
> pointer were well-defined. I image there is a non-trivial amount of
> code "in the wild" that assumes it is well-defined.


The actual use-case is copying data to a "circular" buffer.

unsigned bytes_until_wrap_around = dest_end - write_pointer;
if (buflen < bytes_until_wrap_around)
{
/* COMMON CASE : NO WRAP-AROUND */
memcpy(write_pointer, buf, buflen);
write_pointer += buflen;
}
else
{
/* EXCEPTION : WRAP-AROUND */
int len2 = buflen - bytes_until_wrap_around;
memcpy(write_pointer, buf, bytes_until_wrap_around);
memcpy(dest_base, buf + bytes_until_wrap_around, len2);
write_pointer = dest_base + len2;
}
 
Reply With Quote
 
Francois Grieu
Guest
Posts: n/a
 
      01-26-2011
On 24/01/2011 11:15, Noob wrote:
> Is the call to memcpy with len==0 well-defined, and equivalent
> to a NOP, leaving the entire state machine unchanged?


I won't try to answer that based on the C standard,
but here is a recent (2009-2010) anecdote.

I was developing for an STM7-based embedded system.
The recent, under-active-support C compiler had an
"intrinsic" memcpy that generated tight code when
the source and destination of memcpy were known at
link time and the length fitted a byte.
I found that hard way that this optimization was
broken: when the length had the value 0 and was not
a constant expression (e.g. was a byte variable),
256 bytes got copied.

Francois Grieu
 
Reply With Quote
 
Noob
Guest
Posts: n/a
 
      01-26-2011
Francois Grieu wrote:

> On 24/01/2011 11:15, Noob wrote:
>
>> Is the call to memcpy with len==0 well-defined, and equivalent
>> to a NOP, leaving the entire state machine unchanged?

>
> I won't try to answer that based on the C standard,
> but here is a recent (2009-2010) anecdote.
>
> I was developing for an STM7-based embedded system.
> The recent, under-active-support C compiler had an
> "intrinsic" memcpy that generated tight code when
> the source and destination of memcpy were known at
> link time and the length fitted a byte.
> I found that hard way that this optimization was
> broken: when the length had the value 0 and was not
> a constant expression (e.g. was a byte variable),
> 256 bytes got copied.


My target is an SH-4 from ST, but (luckily) the tool chain
is GNU-based (binutils 2.19.1, GCC 4.3.4, newlib 1.17.0)
 
Reply With Quote
 
J. J. Farrell
Guest
Posts: n/a
 
      01-27-2011
Noob wrote:
>
> Consider
>
> int i = 123;
> int j = 456;
> memcpy(&i, &j, 0);
>
> Is the call to memcpy with len==0 well-defined, and equivalent
> to a NOP, leaving the entire state machine unchanged?
> (i and j unchanged, but everything else too)
>
> I believe memcpy(foo, bar, 0) is indeed equivalent to a NOP.
> Please correct me if I'm wrong.
>
> My C89 draft only states


Why do you say "only" there? The text below fully defines how the
function must behave when the length is 0, in just the same way as it
defines how it must behave when the length is 42.

> 4.11.2.1 The memcpy function
>
> Synopsis
>
> #include <string.h>
> void *memcpy(void *s1, const void *s2, size_t n);
>
> Description
>
> The memcpy function copies n characters from the object pointed to
> by s2 into the object pointed to by s1 . If copying takes place
> between objects that overlap, the behavior is undefined.
>
> Returns
>
> The memcpy function returns the value of s1 .

 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      01-27-2011
"J. J. Farrell" <(E-Mail Removed)> writes:

> Noob wrote:
>>
>> Consider
>>
>> int i = 123;
>> int j = 456;
>> memcpy(&i, &j, 0);
>>
>> Is the call to memcpy with len==0 well-defined, and equivalent
>> to a NOP, leaving the entire state machine unchanged?
>> (i and j unchanged, but everything else too)
>>
>> I believe memcpy(foo, bar, 0) is indeed equivalent to a NOP.
>> Please correct me if I'm wrong.
>>
>> My C89 draft only states

>
> Why do you say "only" there? The text below fully defines how the
> function must behave when the length is 0, in just the same way as it
> defines how it must behave when the length is 42.


The "only" struck me as odd too, but at the same time the text below
does not fully define what memcpy does when the length is 0. In
particular, it does not fully answer the question of whether memcpy(foo,
bar, 0) is a NOP or not so maybe that is the source of the "only".

There is other text elsewhere that defines what happens when either
pointer argument is a null pointer, and the result is pretty much the
opposite of a NOP: it's an "anything" OP!

>> 4.11.2.1 The memcpy function
>>
>> Synopsis
>>
>> #include <string.h>
>> void *memcpy(void *s1, const void *s2, size_t n);
>>
>> Description
>>
>> The memcpy function copies n characters from the object pointed to
>> by s2 into the object pointed to by s1 . If copying takes place
>> between objects that overlap, the behavior is undefined.
>>
>> Returns
>>
>> The memcpy function returns the value of s1 .


--
Ben.
 
Reply With Quote
 
Dr Nick
Guest
Posts: n/a
 
      01-27-2011
"J. J. Farrell" <(E-Mail Removed)> writes:

> Noob wrote:
>>
>> Consider
>>
>> int i = 123;
>> int j = 456;
>> memcpy(&i, &j, 0);
>>
>> Is the call to memcpy with len==0 well-defined, and equivalent
>> to a NOP, leaving the entire state machine unchanged?
>> (i and j unchanged, but everything else too)
>>
>> I believe memcpy(foo, bar, 0) is indeed equivalent to a NOP.
>> Please correct me if I'm wrong.
>>
>> My C89 draft only states

>
> Why do you say "only" there? The text below fully defines how the
> function must behave when the length is 0, in just the same way as it
> defines how it must behave when the length is 42.
>
>> 4.11.2.1 The memcpy function
>>
>> Synopsis
>>
>> #include <string.h>
>> void *memcpy(void *s1, const void *s2, size_t n);
>>
>> Description
>>
>> The memcpy function copies n characters from the object pointed to
>> by s2 into the object pointed to by s1 . If copying takes place
>> between objects that overlap, the behavior is undefined.
>>
>> Returns
>>
>> The memcpy function returns the value of s1 .


I don't think that text is entirely clear. If n is zero we know from
the first sentence that zero characters are copied. But it's far from
clear to me whether if zero bytes have been copied, "copying" has "taken
place", so I remain unsure from the quoted text whether memcpy(x,x,0) is
defined as doing nothing or undefined.
--
Online waterways route planner | http://canalplan.eu
Plan trips, see photos, check facilities | http://canalplan.org.uk
 
Reply With Quote
 
Jorgen Grahn
Guest
Posts: n/a
 
      01-27-2011
On Wed, 2011-01-26, Francois Grieu wrote:
> On 24/01/2011 11:15, Noob wrote:
>> Is the call to memcpy with len==0 well-defined, and equivalent
>> to a NOP, leaving the entire state machine unchanged?

>
> I won't try to answer that based on the C standard,
> but here is a recent (2009-2010) anecdote.
>
> I was developing for an STM7-based embedded system.
> The recent, under-active-support C compiler had an
> "intrinsic" memcpy that generated tight code when
> the source and destination of memcpy were known at
> link time and the length fitted a byte.
> I found that hard way that this optimization was
> broken: when the length had the value 0 and was not
> a constant expression (e.g. was a byte variable),
> 256 bytes got copied.


Your compiler was broken. With all due respect, I see no other lesson
in that. Surely lots of real-life code expects memcpy(foo, bar, n),
with n evaluating to 0, to work as expected.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      01-28-2011
Dr Nick <(E-Mail Removed)> writes:
>> Noob wrote:

<snip>
>>> 4.11.2.1 The memcpy function
>>>
>>> Synopsis
>>>
>>> #include <string.h>
>>> void *memcpy(void *s1, const void *s2, size_t n);
>>>
>>> Description
>>>
>>> The memcpy function copies n characters from the object pointed to
>>> by s2 into the object pointed to by s1 . If copying takes place
>>> between objects that overlap, the behavior is undefined.
>>>
>>> Returns
>>>
>>> The memcpy function returns the value of s1 .

>
> I don't think that text is entirely clear. If n is zero we know from
> the first sentence that zero characters are copied. But it's far from
> clear to me whether if zero bytes have been copied, "copying" has "taken
> place", so I remain unsure from the quoted text whether memcpy(x,x,0) is
> defined as doing nothing or undefined.


I don't think copying zero bytes can constitute copying taking place
between overlapping objects. For one thing, zero byte objects can't
overlap.

Another way to think about it that memcpy(x,x,0) is just the last step
in a sequence of valid copies:

memcpy(x, x+n, n); /* ok (space permitting) */
...
memcpy(x, x+2, 2); /* ok */
memcpy(x, x+1, 1); /* ok */
memcpy(x, x+0, 0); /* ok */

--
Ben.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
memcpy for copying arrays franky.backeljauw@ua.ac.be C++ 13 09-17-2003 11:36 PM
Problem with malloc, realloc, _msize and memcpy Bren C++ 8 09-03-2003 11:01 PM
memcpy problem with padding for word alignment!!! very urgent Ninan Thomas C++ 3 08-22-2003 06:19 AM
Optimized memcpy to reduce cache misses John Edwards C++ 1 08-07-2003 03:01 AM
Re: Optimized memcpy to reduce cache misses David Bradley C++ 0 08-07-2003 12:39 AM



Advertisments