(所有引文均参考N1256,即 C99 加技术勘误 (TC3)。)
的正式定义restrict
在 §6.7.3.1 中给出。我引用下面最重要的子条款。P
是一个restrict
限定类型的指针,T
其范围是一个块B
。一个指针表达式E
被说成是基于 P
它是否依赖于它P
自己的值,而不是它所P
指向的值。
在 的每次执行期间B
,设L
是&L
基于 P 的任何左值。如果L
用于访问X
它指定的对象的值,并且X
也被修改(通过任何方式),则适用以下要求:
T
不应是 const 限定的。
- 用于访问 的值的每个其他左值
X
也应具有基于 的地址P
。
- 就本条而言,修改的每个访问也
X
应被视为修改P
。
- 如果分配了基于另一个受限指针对象
P
的指针表达式的值,与 block 关联,则 的执行应在 的执行之前开始,或者的执行应在分配之前结束。E
P2
B2
B2
B
B2
如果不满足这些要求,则行为未定义。
让我们看看规则对bar
's array
in部分的访问有什么规定foo
。我们从array
的参数列表中声明的限制限定指针开始bar
。为清楚起见,我将对以下参数进行 alpha 转换foo
:
void foo(float* b, float c, unsigned int n) { /*modify b[i]*/ }
指向的存储array
也是通过 修改的b
。第二个要点没关系,&array[i*n]
等同于array+(i*n)
(参见第 6.5.3.2 节)。
如果b
是restrict-qualified,那么我们必须用P
← b
、B
← foo
、P2
← array
、B2
←检查第四个要点bar
。由于B
嵌套在内部B2
(函数的行为就像在这里内联,请参阅 §6.7.3.1.11),因此满足第一个条件。第三个要点(对b[i]
in的访问foo
)也有一个实例,这不是问题。
但是b
没有限制条件。根据 §6.3.2.3.2,“对于任何限定符q,指向非q限定类型的指针可以转换为指向该类型的q限定版本的指针;存储在原始指针和转换指针中的值应比较相等”。因此从array+(i*n)
to的转换b
是明确定义的并且具有明显的含义,因此程序的行为是定义的。此外,由于b
不是restrict
-qualified,它不需要遵守任何线性条件。例如,以下foo
与 结合是合法的bar
:
void qux(float *v, float *w) {
v[0] += w[0];
}
void foo(float* b, float c, unsigned int n)
{
qux(b,b);
}
ADDED: To address your specific concern “in bar() where you pass the address of part of the array to foo()”, this is a non-issue: restrict
applies to the pointer, not the array, and you can perform arithmetic on it (bullet point 2).