Velocity Reviews > Problem with "restrict"

# Problem with "restrict"

Tim Rentsch
Guest
Posts: n/a

 03-16-2013
"christian.bau" <(E-Mail Removed)> writes:

> On Mar 13, 11:01 am, James Kuyper <(E-Mail Removed)> wrote:
>
>> a, b, and c all have the type int*, and therefore must all be
>> correctly aligned for an int. Where do unaligned pointers
>> enter into this?

>
> For unaligned pointers the assumption that an assignment *a = *c
> cannot change the value of *c is wrong. Therefore you need to
> make some argument why *c only needs to be read once. And on many
> implementations int* at arbitrary byte locations are correctly
> aligned for an int. Therefore the bytes of *a and *c can
> partially overlap. [snip example]

This argument is wrong, because of 6.5.16.1 p3. Partial overlap
in such cases is specifically undefined behavior. Therefore
the assumption that *a = *c won't affect the value of *c is
a priori conforming and needs no further justification.

Tim Rentsch
Guest
Posts: n/a

 03-21-2013
"christian.bau" <(E-Mail Removed)> writes:

> On Mar 16, 3:51 am, Tim Rentsch <(E-Mail Removed)> wrote:
>
>> This argument is wrong, because of 6.5.16.1 p3. Partial overlap
>> in such cases is specifically undefined behavior. Therefore
>> the assumption that *a = *c won't affect the value of *c is
>> a priori conforming and needs no further justification.

>
> You just gave exactly the further justification that you claim isn't
> needed.
>
> void f (int* p, int* q)
> {
> char tmp1 [sizeof (int)];
> char tmp2 [sizeof (int)];
>
> *p = 1;
> memcpy (tmp1, p, sizeof (int));
> *q = 2;
> memcpy (tmp2, p, sizeof (int));
>
> if (memcmp (tmp1, tmp2, sizeof (int)) != 0)
> printf ("Can this happen?\n");
> }
>
> The printf can happen on some implementations without any undefined
> behaviour involved.

This example is irrelevant to the point under discussion. Do you
not understand the difference between

*q = 2;

and

*q = *p;

? Of course it is possible that the first of these assignments
can change the value of *p (in the context of the code sample,
and stipulating no undefined behavior). The second cannot.

glen herrmannsfeldt
Guest
Posts: n/a

 03-27-2013
christian.bau <(E-Mail Removed)> wrote:

(snip, someone wrote)

>> This example is irrelevant to the point under discussion. *Do you
>> not understand the difference between

(snip)
> You are of course wrong. On an implementation where the type "int" has
> no alignment restriction, I can write

> char myarray [sizeof (int) + 1];
> int* p = (int *) &myarray [0];
> int* q = (int *) &myarray [1];
> *p = 1;
> *q = *p;

> On a common implementation where sizeof (int) == 4, the first
> assignment sets the bytes in myarray to

The question isn't that you can do that, but what does the C

> 1, 0, 0, 0, unknown (littleendian) or 0, 0, 0, 1, unknown
> (bigendian).

> The second assignment sets the bytes to

> 1, 1, 0, 0, 0 (littleendian) or 0, 0, 0, 0, 1 (bigendian).

> In either case the second assignment modifies the four bytes that p
> points to. Without any undefined behaviour up to this point.

If the C standard says that it is undefined, then it is undefined,
even if your compiler happens to do what you thing it should do.

-- glen

Noob
Guest
Posts: n/a

 03-27-2013
Philip Lantz wrote:

> Read 6.5.16.1p3, as he suggested.

For the interested reader, C99 6.5.16.1p3 states:

> If the value being stored in an object is read from another object
> that overlaps in any way the storage of the first object, then the
> overlap shall be exact and the two objects shall have qualified or
> unqualified versions of a compatible type; otherwise, the behavior
> is undefined.

Regards.

Tim Rentsch
Guest
Posts: n/a

 03-29-2013
"christian.bau" <(E-Mail Removed)> writes:

> On Mar 21, 4:29 pm, Tim Rentsch <(E-Mail Removed)> wrote:
>> "christian.bau" <(E-Mail Removed)> writes:
>> > On Mar 16, 3:51 am, Tim Rentsch <(E-Mail Removed)> wrote:

>>
>> >> This argument is wrong, because of 6.5.16.1 p3. Partial overlap
>> >> in such cases is specifically undefined behavior. Therefore
>> >> the assumption that *a = *c won't affect the value of *c is
>> >> a priori conforming and needs no further justification.

>>
>> > You just gave exactly the further justification that you claim isn't
>> > needed.

>>
>> > void f (int* p, int* q)
>> > {
>> > char tmp1 [sizeof (int)];
>> > char tmp2 [sizeof (int)];

>>
>> > *p = 1;
>> > memcpy (tmp1, p, sizeof (int));
>> > *q = 2;
>> > memcpy (tmp2, p, sizeof (int));

>>
>> > if (memcmp (tmp1, tmp2, sizeof (int)) != 0)
>> > printf ("Can this happen?\n");
>> > }

>>
>> > The printf can happen on some implementations without any undefined
>> > behaviour involved.

>>
>> This example is irrelevant to the point under discussion. Do you
>> not understand the difference between
>>
>> *q = 2;
>>
>> and
>>
>> *q = *p;
>>
>> ? Of course it is possible that the first of these assignments
>> can change the value of *p (in the context of the code sample,
>> and stipulating no undefined behavior). The second cannot.

>
> You are of course wrong. On an implementation where the type "int" has
> no alignment restriction, I can write
>
> char myarray [sizeof (int) + 1];
> int* p = (int *) &myarray [0];
> int* q = (int *) &myarray [1];
> *p = 1;
> *q = *p;
>
> On a common implementation where sizeof (int) == 4, the first
> assignment sets the bytes in myarray to
>
> 1, 0, 0, 0, unknown (littleendian) or 0, 0, 0, 1, unknown
> (bigendian).
>
> The second assignment sets the bytes to
>
> 1, 1, 0, 0, 0 (littleendian) or 0, 0, 0, 0, 1 (bigendian).
>
> In either case the second assignment modifies the four bytes that p
> points to. Without any undefined behaviour up to this point.

As comments from Philip Lantz and Noob have explained, the second
assignment has undefined behavior, because of the rule about no
partial overlap in assignments.

Also, not that this matters, both assignment statements result in
undefined behavior because of effective type rules. The type of
elements in 'myarray' is 'char'. The effective type rules allow
an object whose effective type is 'int' to be accessed using an
lvalue of type 'char' (or any other character type); they do not
allow an object whose effective type is 'char' to be accessed
using an lvalue of type 'int'.

The problem with effective types can be worked around by using
allocated storage instead a declared character array. However,
there remains the problem with undefined behavior because of
the partial-overlap assignment, which is what I've been saying
all along.

AbdulHayee
Junior Member
Join Date: Mar 2013
Posts: 1

 03-31-2013
Thnx...Its useful