R
rainy6144
Does the following code have defined behavior?
double *new_array(unsigned n)
{
double *p = malloc(n * sizeof(double));
unsigned i;
for (i = 0; i < n; i++) p = 0.0;
return p;
}
int main(void)
{
double *restrict x = new_array(10), *restrict y = new_array(10);
x[0] = 1.0;
y[0] = 2.0;
return (int) x[0];
}
The use of "restrict" here is intended to inform the compiler that x
and y do not alias, so that the return value of main() is surely 1.
Without it, and if the compiler does not see the definition of
new_array() when compiling main() (e.g. because they are in different
translation units), it must assume that the two calls to new_array()
might return the same pointer.
However, according to 6.7.3.1p4 of the standard, the code seems to
have undefined behavior, because the lvalue "x[0]", whose address is
based on restricted pointer x, is used to access the object x[0] (and
it is modified), yet the initialization of that object to 0.0 in
new_array() uses the lvalue p[0], whose address p is not based on x
(indeed, x has not been initialized or used by that time). The
problem is that the no-non-based-alias restriction seems to apply to
the whole block containing the declaration of the restricted pointer
(in this case, the main() function), even before the pointer is
initialized.
Is my understanding correct? I suppose it is okay to do this:
int main(void)
{
double *x0 = new_array(10), *y0 = new_array(10);
{
double *restrict x = x0, *restrict y = y0;
x[0] = 1.0; y[0] = 2.0; return (int) x[0];
}
}
But it is clearly a bit too verbose.
double *new_array(unsigned n)
{
double *p = malloc(n * sizeof(double));
unsigned i;
for (i = 0; i < n; i++) p = 0.0;
return p;
}
int main(void)
{
double *restrict x = new_array(10), *restrict y = new_array(10);
x[0] = 1.0;
y[0] = 2.0;
return (int) x[0];
}
The use of "restrict" here is intended to inform the compiler that x
and y do not alias, so that the return value of main() is surely 1.
Without it, and if the compiler does not see the definition of
new_array() when compiling main() (e.g. because they are in different
translation units), it must assume that the two calls to new_array()
might return the same pointer.
However, according to 6.7.3.1p4 of the standard, the code seems to
have undefined behavior, because the lvalue "x[0]", whose address is
based on restricted pointer x, is used to access the object x[0] (and
it is modified), yet the initialization of that object to 0.0 in
new_array() uses the lvalue p[0], whose address p is not based on x
(indeed, x has not been initialized or used by that time). The
problem is that the no-non-based-alias restriction seems to apply to
the whole block containing the declaration of the restricted pointer
(in this case, the main() function), even before the pointer is
initialized.
Is my understanding correct? I suppose it is okay to do this:
int main(void)
{
double *x0 = new_array(10), *y0 = new_array(10);
{
double *restrict x = x0, *restrict y = y0;
x[0] = 1.0; y[0] = 2.0; return (int) x[0];
}
}
But it is clearly a bit too verbose.