我正在尝试调整以下版本的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
时感到非常不舒服,并且不想仅依靠我自己的判断。
答案 0 :(得分:3)
为了符合标准,唯一的限制是操纵通过restrict
指针接收的任何对象的所有指针表达式应该是基于的在该指针上。它不要求指针表达式具有相同的类型。因此,在这种意义上,通过这些size_t*
访问对象不是违反约束或UB。
我不确定读取您通过*wd
修改的对象的一部分的值与*d
不会别名,因为指针类型不同。但正如你所说,你不这样做,所以这应该是安全的。
uintptr_t
的低位反映了转换为它的指针的对齐属性。这可能适用于我们在日常使用中遇到的所有体系结构,但不受标准保证。甚至C11也只是说“字节地址的倍数”,而没有任何东西可以指明它是什么。