在 C 中使用限制指针时,可以使用其初始标识符来更改变量吗?
在 C 中使用 restrict
指针时,是否可以使用其初始标识符更改变量?例如:
int foo = 0;
int * restrict fooPtr = &foo;
++(*fooPtr); // Part 1: foo is 1 (OK)
++foo; // Part 2: foo is 2 (Is this OK?)
int * fooPtr2 = &foo;
++(*fooPtr2); // Part 3: foo is 3 (BAD: You shouldn't access via a second pointer)
...在创建 restrict
fooPtr 后,我通过 foo 更改了 foo 的值。
第 1 部分对我来说看起来不错。我对第 2 部分感到困惑。根据我对 restrict
的理解,第 3 部分 很糟糕(编译器允许它,但其行为未定义,程序员应该不这样做)。
When using a restrict
Pointer in C, is it OK to change the variable using its initial Identifier? For example:
int foo = 0;
int * restrict fooPtr = &foo;
++(*fooPtr); // Part 1: foo is 1 (OK)
++foo; // Part 2: foo is 2 (Is this OK?)
int * fooPtr2 = &foo;
++(*fooPtr2); // Part 3: foo is 3 (BAD: You shouldn't access via a second pointer)
...I changed the value of foo through foo after the restrict
fooPtr was created.
Part 1 looks OK to me. I'm confused about Part 2. And from what I understand about restrict
, Part 3 is bad (compiler allows it, but its behavior is undefined, and it's up to the programmer not to do that).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
不,第二部分不行。
该标准的具体部分是6.7.3.1/4。这一部分相当密集,需要重新阅读几次,但 P 是一个限制指针,X 是它用来访问的某个对象,并且它被修改了。因此,在您的示例中,P 是
fooPtr
,X 是foo
。然后:“基于”在上一段中定义,总而言之,左值
foo
确实不具有基于限制指针 P 的地址。因此当您通过对象foo
自己的名称访问该对象时,规则就会被破坏。出于完全相同的原因,第 3 部分也不行,左值 *fooPtr2 也不是基于 P,但也用于访问 X。
我说“不行” - 准确地说, 1+2 的组合会引发未定义的行为,1+3 的组合也是如此。只要您实际上不通过限制指针访问该对象,限制的定义就不会“生效”。如果您愿意,可以删除第 1 部分,保留未使用的限制指针,然后 2 和 3 就可以了。
No, Part 2 is not OK.
The specific part of the standard is 6.7.3.1/4. This section is pretty dense, and takes a few re-reads, but P is a restrict pointer, and X is some object it is used to access, and which is modified. So in your example P is
fooPtr
and X isfoo
. Then:"based on" is defined in the previous paragraph, and to summarize, the lvalue
foo
does not have its address based on the restrict pointer P. So the rule is broken when you access the objectfoo
through its own name.Part 3 is not OK for exactly the same reason, the lvalue
*fooPtr2
isn't based on P either, but is also used to access X.I say "not OK" - to be precise, the combination of 1+2 provokes undefined behavior, as does the combination of 1+3. As long as you don't actually access the object through the restrict pointer, none of the definition of restrict "kicks in". If you wanted to you could remove Part 1, retain the unused restrict pointer, and then 2 and 3 would be OK.
是的,“第 3 部分”是未定义的行为。来自 C99 规范(6.7.3,第 7 段):
Yes, "part 3" is undefined behaviour. From the C99 spec (6.7.3, paragraph 7):
我想说#2 很糟糕。例如,编译器可能会通过将 *fooPtr 处的值加载到寄存器中来进行优化,然后稍后(在 ++foo 之后)再次将该寄存器值写回 foo,这样 ++foo 就会丢失。
I'd say #2 is bad. For instance, the compiler might optimize by loading the value at *fooPtr into a register, and then write that register value back out to foo again later - after your ++foo, so that the ++foo is lost.
假设问题的所有部分都出现在同一个块中,则直接访问 foo 的值(第 2 部分)或通过另一个指针访问它(第 3 部分)是不行的:
restrict
的正式定义很难遵循(至少对我来说如此),但是以下不太正式的定义标准中的描述也很好地总结了这一点(至少对于这种情况):Assuming that all of the parts of your question occur in the same block, it's not OK to access the value of
foo
directly (part 2) nor to access it via another pointer (part 3):The formal definition of
restrict
is quite difficult to follow (at least it is for me), however the following less formal description also from the standard sums it up pretty well (at least for this case):