restrict query

P

pemo

In Harbison and Steele's book, they say that using 'restrict' allows
functions like memcpy() to be prototyped like this:

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

But this seems a mite dangerous to me ... a restricted pointer ... is
*assumed* to be the only to access an object.

So, mightn't using such a prototype subtly imply [to some] that the compiler
will *actively check* [completely!] that s1 and s2 do not point to the same
object [or that s1/s2's memory does not overlap]? It couldn't do this
[IMHO] without adding code to check, and thus impacting the very thing that
restrict is meant to aid - optimisation.

If the prototype should be read/interpreted as 'don't let s1 and s2 have the
same value' [or overlap], is using a prototype like this simply a way of
documenting this?
 
C

Christian Bau

"pemo said:
In Harbison and Steele's book, they say that using 'restrict' allows
functions like memcpy() to be prototyped like this:

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

But this seems a mite dangerous to me ... a restricted pointer ... is
*assumed* to be the only to access an object.

So, mightn't using such a prototype subtly imply [to some] that the compiler
will *actively check* [completely!] that s1 and s2 do not point to the same
object [or that s1/s2's memory does not overlap]? It couldn't do this
[IMHO] without adding code to check, and thus impacting the very thing that
restrict is meant to aid - optimisation.

If the prototype should be read/interpreted as 'don't let s1 and s2 have the
same value' [or overlap], is using a prototype like this simply a way of
documenting this?

In the C Standard before C99, it was already undefined behavior if
source and destination for memcpy would overlap. But if you had written
your own memcpy function, like (using char* to make it shorter)

void my_memcpy (char* dst, char* src, size_t n)
{
for (; n > 0; --n) *dst++ = *src++;
}

then there is of course no undefined behavior at all (the point is of
course that I could write a different implementation like

void my_memcpy (char* dst, char* src, size_t n)
{
for (; n > 0; --n) dst [n-1] = src[n-1];
}

which would also have defined, but different behavior). Writing a
function that behaved _exactly_ like memcpy, _including_ having
undefined behavior when memcpy has undefined behavior (obviously without
just calling memcpy) is quite difficult

Using restrict, I can write a function

void my_memcpy (char* restrict dst, const char* restrict src, size_t
n)
{
for (; n > 0; --n) *dst++ = *src++;
}

that reflects _exactly_ the behavior of memcpy.

So basically, the "restrict" is a hint; the prototype using "restrict"
plus an obvious implementation in portable C would lead to undefined
behavior exactly as described by the C Standard.
 
K

Keith Thompson

pemo said:
In Harbison and Steele's book, they say that using 'restrict' allows
functions like memcpy() to be prototyped like this:

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

But this seems a mite dangerous to me ... a restricted pointer ... is
*assumed* to be the only to access an object.

So, mightn't using such a prototype subtly imply [to some] that the compiler
will *actively check* [completely!] that s1 and s2 do not point to the same
object [or that s1/s2's memory does not overlap]? It couldn't do this
[IMHO] without adding code to check, and thus impacting the very thing that
restrict is meant to aid - optimisation.

If the prototype should be read/interpreted as 'don't let s1 and s2 have the
same value' [or overlap], is using a prototype like this simply a way of
documenting this?

An implementation is not expected to check that restricted pointers
don't point to the same object. The "restrict" qualifier is a promise
made by the programmer to the compiler. The compiler is allowed to
assume that this promise is valid, and can perform some additional
optimizations based on that promise.

The only effect of the "restrict" qualifier is to make some things
that would otherwise be valid invoke undefined behavior. If you use
the "restrict" qualifier incorrectly, you're giving the compiler
permission to shoot you in the foot (i.e., if you lie to the compiler
it will get its revenge).

Here's what the standard says (C99 6.7.3p7):

An object that is accessed through a restrict-qualified pointer
has a special association with that pointer. This association,
defined in 6.7.3.1 below, requires that all accesses to that
object use, directly or indirectly, the value of that particular
pointer. The intended use of the restrict qualifier (like the
register storage class) is to promote optimization, and deleting
all instances of the qualifier from all preprocessing translation
units composing a conforming program does not change its meaning
(i.e., observable behavior).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,225
Members
46,815
Latest member
treekmostly22

Latest Threads

Top