-
const
is it safe having a function like:
Code:
void func(void *out_p, const void *in_p);
and pass a pointer to the same object as both arguments?
since the object passed as the arguments is both - const and non-const.
so might optimization produce wrong code in that case - or are arguments skipped by optimization anyway?
example:
.) read from *in_p
.) modify *out_p - thus the object pointed to by in_p has changed.
read from *in_p again. since the object pointed to by in_p was declared const, the compiler might think it has not changed and do some optimization. so instead of reading the changed version, the original version would be read.
-
depends
completely valid be careful parameters
Kuphryn
-
Compiler optimization should never change the expected behavior of a program. If whatever the object is can handle being written to and read from at the same time, then the fact that you pass two pointers to the same object shouldn't have any negative effect.
-
You might have a problem passing the same object by pointer like that, but it would not be because of optimisation. More likely you might run into a problem if func() accesses in_p throughout it's execution, expecting the value(s) pointed to to stay the same.
-
well i couldn't make up a good example, where passing the same object as const and non-const would make sense, WITHOUT creating a temporary copy
in the function.
(probably, because there is none)
anyway:
Code:
void func(IntVector &r_out, const IntVector &r_in)
{
register tmp = r_in[1]; // store r_in[1] into a register
r_out[1] = r_in[0]; // assume that (&r_out == &r_in) holds in this example, so r_in[1] is changed indirectly
std::cout << r_in[1] << std::endl; // ?! what is being printed here, the original r_in[0] (which would be expected) or the original r_in[1]
}
so an optimizing compiler might assume, that r_in[1] could be replaced by the register variable tmp - thus not re-read it again.
this is not the expected behaviour when looking at the code.
on the other hand, writing to an output object, which modifies the input object at the same time, and then reading modified data from the input object again is a logic mistake anyway.
(because when having a function that accepts input and output as seperate arguments, then its clearly intended for having different objects passed to it. if such function should be able to handle the case, that input and output refer to the same object, then a temporary copy of the input has to be created.)
-
> Compiler optimization should never change the expected behavior of a program
This is only true of a correct program.
Optimisation frequently breaks poorly written code for one reason or another.
Most standard C library functions (memmove is a noted and specific exception) react pretty badly to overlapping memory blocks.
> this is not the expected behaviour when looking at the code
No, but you might expect it when you turn on the optimiser, and expect references through const to be read only once. If you then go and change it via another route, then you're in for a surprise.
This is exactly the reason (namely aliasing) which prevents some kinds of optimisation from taking place.
It's also the reason why C99 added the "restrict" keyword to allow checks to be performed to ensure that multiple references to the same object (possibly with different attributes) do not exist.
-
>> Optimisation frequently breaks poorly written code for one reason or another.
You are right, assuming by "poorly written" you mean incorrect. I might call the original code poorly written even if it was legally valid, but the optimization shouldn't break it if that was the case.
-
Some compilers (such as G++) have proprietary extensions that allow the programmer to mark arguments as non-aliased, i.e. the optimizer may assume that all pointers point to different objects. Passing the same object to such a function may cause problems.