如果我有两个指针(基本上是begin
和end
),则使用restrict
限定。 begin
指针用于解除引用/读取,end
指针是一个永不解除引用的一个过去的指针,仅用于检查范围的大小(通过{ {1}})。消耗范围后,我希望end - begin
和begin
相等,end
为0,但此时两个指针永远不会被解除引用。
鉴于end - begin
对指针的限制,是否需要明确定义的行为来减去和比较这两个指针?
我有一些代码如下:
restrict
我想更改它,以便在阅读时不必修改#include <stddef.h>
struct Reader {
const char* restrict data;
size_t size;
};
char read_char(struct Reader* reader) {
--reader->size;
return *reader->data++;
}
int main(int argc, char* argv[]) {
struct Reader reader = {
.data = argv[1],
.size = argv[1] ? strlen(argv[1]) : 0,
};
if (reader.size > 0) {
return read_char(&reader);
}
return 0;
}
和data
,只需要修改size
:
data
考虑到#include <stddef.h>
struct Reader {
const char* restrict data;
const char* restrict end; // Not sure if this should be restrict or not.
};
char read_char(struct Reader* reader) {
return *reader->data++;
}
int main(int argc, char* argv[]) {
struct Reader reader = {
.data = argv[1],
.end = argv[1] + (argv[1] ? strlen(argv[1]) : 0),
};
if (reader.end - reader.data > 0) { // Is this okay?
return read_char(&reader);
}
return 0;
}
对指针的限制,这是允许的吗?
答案 0 :(得分:5)
TL; DR:我在阅读标准时允许您使用。
使用restrict
- 限定指针的标准要求都与别名和对指向对象的访问有关。我发现使用这样的指针作为指针差异运算符(-
)的操作数没有限制,并且这些限制与restrict
的目的不一致(这是为了提供更大的优化机会)。
相反,通过添加整数从restrict
- 限定指针获得的指针值是&#34;基于&#34;原始指针在某种意义上对标准有重要意义。粗略地说,通过这样的指针访问指向对象是可以接受的,而通过指向同一对象的指针来访问该对象是不可接受的,该对象不是基于&#34;限制指针。
此外,我不认为Reader.end
需要restrict
- 合格,我也不认为这样的资格可以帮助你。但是,您必须确保Reader.end
和从它派生的任何指针都不用于访问数据;您必须只使用Reader.data
。在main()
中也是如此。
另一方面,如果你无处修改指向对象,几乎所有这些都没有实际意义。
答案 1 :(得分:0)
标准或基本原理中的任何内容均未暗示禁止对限制限定的指针进行比较或计算的意图。标准定义一个指针“基于”另一个指针的概念的方式,然而与比较却产生了怪异的相互作用。例如,给出类似这样的内容:
int test(int *restrict p, int *q, int i)
{
p[i] = 1;
if (p+1 == q)
p[1] = 2;
return p[i];
}
用指向所标识数组副本的指针替换p
会阻止对p[1]
的赋值,这使人们无法解决这样的替换是否会影响该赋值中使用的地址的问题。尽管p[1]
是基于p
的,而且这种比较似乎会影响这一点是很荒谬的,但是clang和gcc都不认为上面的左值p[1]
是基于{与左值p
相同的p[i]
。