4

在 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)

...在创建fooPtr后,我通过foo更改了foo的值。restrict

第 1 部分对我来说看起来不错。我对第 2 部分感到困惑。根据我的理解restrict第 3 部分很糟糕(编译器允许这样做,但它的行为是未定义的,程序员不这样做)。

4

4 回答 4

4

不,第 2 部分不行。

标准的具体部分是 6.7.3.1/4。这部分内容非常密集,需要重读几次,但 P 是一个限制指针,而 X 是它用于访问的某个对象,并且已被修改。所以在你的例子中 P 是fooPtr并且 X 是foo。然后:

用于访问 X 值的每个其他左值也应具有基于 P 的地址。

“基于”在上一段中定义,总而言之,左值foo没有基于限制指针P的地址。因此,当您通过自己的名称访问对象时,规则被打破foo

由于完全相同的原因,第 3 部分不可行,左值*fooPtr2也不基于 P,但也用于访问 X。

我说“不好”——准确地说,1+2 的组合会引发未定义的行为,1+3 的组合也是如此。只要您实际上不通过限制指针访问对象,限制的定义就不会“开始”。如果您愿意,可以删除第 1 部分,保留未使用的限制指针,然后 2 和 3 就可以了。

于 2010-10-14T18:08:31.787 回答
1

是的,“第 3 部分”是未定义的行为。从 C99 规范(6.7.3,第 7 段):

通过限制限定指针访问的对象与该指针具有特殊关联。这种关联,在下面的 6.7.3.1 中定义,要求所有对该对象的访问,直接或间接地使用该特定指针的值。

于 2010-10-14T18:04:55.193 回答
1

我会说#2很糟糕。例如,编译器可能会通过将 *fooPtr 处的值加载到寄存器中进行优化,然后稍后再将该寄存器值写回 foo - 在您的 ++foo 之后,这样 ++foo 就会丢失。

于 2010-10-14T18:09:25.077 回答
1

foo假设您的问题的所有部分都出现在同一个块中,直接访问(第 2 部分)的值或通过另一个指针(第 3 部分)访问它是不行的:

  • 6.7.3.1 限制的正式定义

用于访问 X 值的每个其他左值也应具有基于 P 的地址。

的正式定义restrict很难遵循(至少对我来说是这样),但是标准中的以下不太正式的描述也很好地总结了它(至少在这种情况下):

通过限制限定指针访问的对象与该指针具有特殊关联。这种关联,在下面的 6.7.3.1 中定义,要求对该对象的所有访问都直接或间接地使用该特定指针的值。

于 2010-10-14T18:11:37.850 回答