混淆调整代码以使用限制限定符

时间:2012-09-04 01:26:26

标签: c c99 strict-aliasing restrict-qualifier

我正在尝试调整以下版本的stpcpy函数以使用restrict - 限定指针作为其参数和内部,但我不确定是否只是添加限定符将导致未定义的行为。

#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;
}

假设C99 6.7.3.1中有关访问对象的规则仅涉及所访问的单个对象而不是整个数组,我认为它可能没问题,因为所写的元素只能访问一次,而且只能用于写入。但是我在这一点上使用restrict时感到非常不舒服,并且不想仅依靠我自己的判断。

1 个答案:

答案 0 :(得分:3)

为了符合标准,唯一的限制是操纵通过restrict指针接收的任何对象的所有指针表达式应该是基于在该指针上。它不要求指针表达式具有相同的类型。因此,在这种意义上,通过这些size_t*访问对象不是违反约束或UB。

我不确定读取您通过*wd修改的对象的一部分的值与*d不会别名,因为指针类型不同。但正如你所说,你不这样做,所以这应该是安全的。

BTW,代码做了一个不一定是可移植的重要假设,即uintptr_t的低位反映了转换为它的指针的对齐属性。这可能适用于我们在日常使用中遇到的所有体系结构,但不受标准保证。甚至C11也只是说“字节地址的倍数”,而没有任何东西可以指明它是什么。