Question

I'm trying to adapt the following version of the stpcpy function to use restrict-qualified pointers as its arguments and internally, but I'm not sure if simply adding the qualifier would result introduce undefined behavior.

#define ALIGN (sizeof(size_t)-1)
#define ONES ((size_t)-1/UCHAR_MAX)
#define HIGHS (ONES * (UCHAR_MAX/2+1))
#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)

char *__stpcpy(char *d, const char *s)
{
        size_t *wd;
        const size_t *ws;

        if (((uintptr_t)s & ALIGN) == ((uintptr_t)d & ALIGN)) {
                for (; (*d=*s) && ((uintptr_t)s & ALIGN); s++, d++);
                if (!*s) return d;
                wd=(void *)d; ws=(const void *)s;
                for (; !HASZERO(*ws); *wd++ = *ws++);
                d=(void *)wd; s=(const void *)ws;
        }
        for (; (*d=*s); s++, d++);

        return d;
}

Assuming the rules in C99 6.7.3.1 about accessing an object pertain only to the individual object accessed and not the whole array, I think it may be fine, as the elements written are only accessed once, and only for writing. But I'm rather uncomfortable with using restrict at this point and don't want to rely on just my own judgement.

Was it helpful?

Solution

To comply to the standard the only restriction is that all pointer expression that manipulate any of the objects that the function received through the restrict pointers should be based on that pointer. It doesn't require the pointer expression to be of the same type. So in that sense accessing the object through these size_t* isn't a constraint violation or UB.

I wouldn't be sure if reading the value of a part of the object that you modified through *wd with *d wouldn't alias, since the pointer types differ. But as you say, you don't do that, so this should be safe.

BTW, the code makes one important assumption that is not necessarily portable, namely that the low bits of an uintptr_t reflect the alignment properties of the pointer that you converted to it. This is probably true on all architectures that we encounter in daily use, but not guaranteed by the standard. Even C11 only says something about "multiples of a byte address" where there is nothing that specifies what that would be.

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