B
Branimir Maksimovic
Branimir Maksimovic said:Flash Gordon said:Branimir said:Christian Bau wrote:
William Hughes wrote:
Branimir Maksimovic wrote:
Mark McIntyre wrote:
On 26 Oct 2005 09:00:34 -0700, in comp.lang.c , "Branimir
Maksimovic"
Keith Thompson wrote:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^This is important in regard of what makes original poster conclude
that memcpy(&x,&y,sizeof(x)) should be always faster or equal then
memcpy(&x,&y,sizeof(x)-1). ^^^^^^^^^^^^^^^^^^^^^^^^^
Christian Bau (who was not the original poster) did not conclude this.
His point was that memcpy(&x,&y,sizeof(x)) *could* be faster
than memcpy(&x,&y,sizeof(x)-1).
Clearly memcpy parameter is not about number of copy operations, and
in this respect his conclusion is invalid, because if
memcpy(&x,&y,sizeof(x)-1) does not produce trap value, ^^^^^^^^^^^^^^^^^^^^^^^^^
implementation can use load register, store register,
Nope, you have to preseve the last byte.
What byte?
Implementation can do anything that does not change observable
behavior. Since you have stored something that is not
valid double object, last byte would not change observable behavior, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
because using x as a double further in program
produces undefined behavior anyway.
Example:
double x, y;
x = 0.0; y = 1.0 / 3.0;
((unsigned char *) &x) [sizeof (x) - 1] = 79;
memcpy (&x, &y, sizeof (x) - 1);
Looks the same to me.
Oh original example which started whole discussion was lost. Sorry.
how about original example with:
memcpy (&x, &y, sizeof (x));
Christian Bau was responding to a bit about memcpy (&x, &y, sizeof (x) -
1); and his post looks entirely correct to me.
if (((unsigned char *) &x) [sizeof (x) - 1] != 79)
printf ("This implementation is broken!\n");
I stored the number 79 into the last byte of x. The memcpy is not
allowed to overwrite it, so it must contain the value 79 after the call
to memcpy. There is no undefined behavior. There might be undefined
behavior if I _would_ use x as a double, but I don't, so there is no
undefined behavior.
Come on, this has completely different semantics then original example.
This thread has been talking about both sizeof (x) and sizeof (x) - 1 for
ages.
You have created valid unsigned char object at a given address
and dropped memcpy with sizeof(x). Stop playing around.
All bytes can always be read as unsigned char values, An alternative
example would have been taking a copy of the byte that memcpy is not
allowed to change and verifying afterwards that it had not changed.
Even as I said that will shut up, couldn't resist to this one.
This is not enough to trick implementation to force preservation of said
byte.
Implementation can simply replace
if (((unsigned char *) &x) [sizeof (x) - 1] != 79)
with if (0) and change the byte without problem.
Since everything happens at same scope, this does not affect observable
behavior and here we are again ; one must to do something like this
instead:
double x,y;
((unsigned char *) &x) [sizeof (x) - 1] = 79;
memcpy (&x, &y, sizeof (x) - 1);
void foo(unsigned char*); /* some external function not visible in this
translation unit */
foo( ((unsigned char *) &x) + sizeof (x) - 1 );
Now implementation must preserve that byte because it does not knows
what happens in "foo".
But in case that we don't initialize the byte, trick is little bit
different:
double x,y;
unsigned char* p= ((unsigned char *) &x) +sizeof (x) - 1;
unsigned char t = *p;
memcpy (&x, &y, sizeof (x) - 1);
unsigned char foo(unsigned char*); /* some external function not visible
in this translation unit */
assert(foo(p)==t); /* this forces implementation to preserve
the byte since foo may or may not return same value */
But I missed one major point. memcpy can be completely optimised out
since that does not change behavior of program.
So......
double x,y;
unsigned char* p= ((unsigned char *) &x) +sizeof (x) - 1;
unsigned char t = *p;
memcpy (&x, &y, sizeof (x) - 1);
unsigned char foo(unsigned char*); /* some external function not visible
in this translation unit */
void bar(double *,double*); /* external */
bar(&x,&y); /* this finally forces compiler to actually *perform* memcpy
because it does not knows if corresponding chars would
be checked for equality */
assert(foo(p)==t); /* this forces implementation to preserve
the byte since foo may or may not return same value */
Finally I think that I got it right. Perhaps not? compiler can always
outsmart programmer