Question

If dot_product is declared as

float dot_product(const float* restrict a, const float* restrict b, unsigned n);

would calling it with

dot_product(x, x, x_len)

be "undefined", according to the C99 standard?

Edit

x is a pointer, of course, pointing to sizeof(float) * x_len bytes of memory, x_len is unsigned. This question is about aliasing.

Was it helpful?

Solution

I do not have the original C99 (that is, ISO9899:1999) text; I only have a copy of ISO9899:2007:TC3. I expect this text, taken from page 111 of that document, is very similar to the text in the C99 standard.

6.7.3.1 Formal definition of restrict

...

10. EXAMPLE 3

The function parameter declarations

    void h(int n, int * restrict p, int * restrict q, int * restrict r)
    {
        int i;
        for (i = 0; i < n; i++)
            p[i] = q[i] + r[i];
    }

illustrate how an unmodified object can be aliased through two restricted
pointers. In particular, if a and b are disjoint arrays, a call of the form
h(100, a, b, b) has defined behavior, because array b is not modified within
function h.

This seems to clearly call out functions of the form you asked about as having defined behavior, provided the aliased pointers are used for read-only access. Writing through either of the aliased pointers would invoke undefined behavior.

OTHER TIPS

First I don't think that the call itself is UB, UB can only occur inside the function, if the pointers that are passed as parameters are used in a way that conflicts with the specification of restrict. (UB makes not much sense for the call, if that (w/sh)ould be forbidden, this should have been made a constraint violation and not UB.)

Then, UB related to restrict can only appear, if the pointed to object is modified "in any way". So as long as your vectors aren't modified, everything is fine. Inside your function this shouldn't happen, because of the const qualification. And if something outside (say a different thread or a signal handler) modifies your vectors, you are screwed, anyhow.

Yes. It will invoke undefined behavior.

If the restrict keyword is used and the function is declared as :

float dot_product(const float* restrict a, const float* restrict b, unsigned n);

then the compiler is allowed to assume that a and b point to different locations and updating one pointer will not affect the other pointers. The programmer, not the compiler, is responsible for ensuring that the pointers do not point to identical locations.

Since your function call is

dot_product(x, x, x_len)  

which is passing the same pointer x to the function, updating any of a or b will affect other causing undefined behavior.

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