Question

Consider these two functions:

void foo(char * __restrict localPtr)
{
    // some work with localPtr
}

void bar(char * __restrict ptr)
{
    // some work with ptr
    foo(_ptr);
    // some other work with ptr
}

As ptr has been declared __restrict in bar, is calling foo() dangerous? By dangerous, I mean that the memory zone pointed by localPtr overlaps ptr's one. What are the guidelines about that?

Was it helpful?

Solution

The restrict qualifier means that the only way for the called function to access the memory passed as localPtr in foo is via that pointer; there are no aliases to that memory. This might enable the optimizer to produce better code because it doesn't have to worry about another pointer also changing the data.

In this context, and in most others, the restrict qualifier places an onus on you, the programmer making the calls, to ensure that you are honouring the 'no aliases' requirement.

There is no visible danger from the code above.

Note that most usually you have multiple pointers in the argument list when restrict is used. From the C standard, compare:

void *memcpy(void *restrict s1, const void *restrict s2, size_t n);
void *memmove(void *s1, const void *s2, size_t n);

The first (memcpy()) says that the chunks of memory [s1 .. s1+n-1] and [s2 .. s2+n-1] must not overlap; you will get undefined behaviour if they do in fact overlap. The second (memmove()) does not impose that requirement.


But isn’t the call to foo() creating another pointer that is changing the data?

Yes, No, Sort Of ... but mostly No.

The pointer in foo() is certainly passed to bar(), but while bar() is running, the only way bar() can get at the memory is through the pointer it was passed. Thus bar() is able to be compiled on the assumption that it has no alias for the memory it is working with.

When the compiler is processing foo(), it knows (ensures) that there is a sequence point after the arguments to bar() are evaluated and before the function is called, and another when the function returns. It knows that the data might have been modified by bar() since it was not passed a const char *. Therefore, it will generate the code to account for these possibilities. However, the compiler also knows that the only way that foo() can access the memory addressed by localPtr is via localPtr (that's what the restrict says), and it can proceed based on that assumption.

So, there is a second copy of the pointer while bar() is being called, but it is not in violation of the rules of restrict in any way.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top