user2711115
user2711115

Reputation: 457

Confused about C restrict qualifier

First, cppreference has the following to say about restrict:

During each execution of a block in which a restricted pointer P is declared (typically each execution of a function body in which P is a function parameter), if some object that is accessible through P (directly or indirectly) is modified, by any means, then all accesses to that object (both reads and writes) in that block must occur through P (directly or indirectly), otherwise the behavior is undefined.

But below this paragraph it says:

Restricted pointers can be assigned to unrestricted pointers freely, the optimization opportunities remain in place as long as the compiler is able to analyze the code:

void f(int n, float * restrict r, float * restrict s) {
   float * p = r, * q = s; // OK
   while(n-- > 0) *p++ = *q++; // almost certainly optimized just like *r++ = *s++
}

In the above, r[0] is an object that is accessible through restricted pointer r, and it is getting accessed through p, which seems to contradict the first paragraph (that accesses to r[0] must occur solely through r) ?

Second:

Assignment from one restricted pointer to another is undefined behavior, except when assigning from a pointer to an object in some outer block to a pointer in some inner block (including using a restricted pointer argument when calling a function with a restricted pointer parameter) or when returning from a function (and otherwise when the block of the from-pointer ended).

So, is the following code ok?

void foo(char* restrict a, size_t s)
{
    for(char* restrict aa = a; aa < a + s; ++aa) // Is aa in an inner block?
    {
        *aa = '\0';
    }
}

Upvotes: 6

Views: 401

Answers (1)

Serge Ballesta
Serge Ballesta

Reputation: 149075

The key on example 1 is that the lvalue *p that is used to access the underlying array pointed by r has its address based on r. Said differently, it is an indirect access through r. As *q also has its address based on s, all the accesses occur, even if indirectly, through the original restricted pointers: no UB here.

Example 2 is even more trivial. You declare a new restricted pointer based on the original one. So there is no UB either. But in example 2, both restricted qualifiers add exactly no value, because inside the block (the foo function definition) only one single pointer is used because aa is based on a.

In example 1, the restrict qualifiers declare to the compiler that the arrays pointed by r and s do not overlap: no access through r (directly or indirectly through p) should touch the array pointed to by s.

Upvotes: 2

Related Questions