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';
}
}
The restrict qualifier can be used in the declaration of a structure member. A compiler can assume, when an identifier is declared that provides a means of access to an object of that structure type, that the member provides the sole initial means of access to an object of the type specified in the member declaration.
The restrict (or __restrict or __restrict__ ) 1 type qualifier is an indication to the compiler that, if the memory addressed by the restrict -qualified pointer is modified, no other pointer will access that same memory.
In the C programming language, restrict is a keyword, introduced by the C99 standard, that can be used in pointer declarations. By adding this type qualifier, a programmer hints to the compiler that for the lifetime of the pointer, no other pointer will be used to access the object to which it points.
In C, restrict is a “type qualifier”. (Other things in this category are const and volatile ). This means, for some type T , we can write T restrict to get another type. For example, char const * restrict is a type. Actually, it only applies to pointer types, i.e. T * restrict .
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With