这是四个代码片段。为什么保证(或不保证)此代码能够生成定义良好的行为?
struct B;
struct A { struct B *restrict b1, *restrict b2; };
struct B { struct A *restrict a1, *restrict a2; };
void f1(int *restrict p) {
{
int *restrict p2 = p;
*p2 = 0;
}
}
static inline void f2helper(int *restrict p) {
*p = 0;
}
void f2(int *restrict p) {
f2helper(p);
}
void f3(int *restrict p, size_t s) {
int * p2 = p + s;
while (p2 > p)
*--p2 = 0;
}
答案 0 :(得分:1)
最初,问题包含保证不编译的代码:
struct B;
struct A { struct B *restrict b1, b2; };
struct B { struct A *restrict a1, a2; };
第一个结构相当于:
struct A { struct B *restrict b1; struct B b2; };
并且您不能拥有一个不完整类型的元素(尽管您可以使用指向不完整类型的受限指针),因此b2
无效。
指出了这一点,提出了两种可能性:
'要么':
struct B;
struct A { struct B *restrict b1, *restrict b2; };
struct B { struct A *restrict a1, *restrict a2; };
'或者':
struct B;
struct A { struct B *restrict b1; int b2; };
struct B { struct A *restrict a1; int a2; };
'要么'选项是预期的,以及现在列出的问题。
'要么'结构在语法上是有效的,但几乎没用;你可以创建它们,但它们不能真正掌握任何有用的信息。
struct A a1, a2;
struct B b1, b2;
a1 = (struct A){ &b1, &b2 };
a2 = (struct A){ &b2, &b1 };
b1 = (struct B){ &a1, &a2 };
b2 = (struct B){ &a2, &a1 };
你真的无法做到这些。
'或'结构在语法上也是有效的,可以有一些用处,虽然很难看出它们非常有用。
据我所知,所有这三套功能都很干净。
C11的第6.7.3节类型限定符(ISO / IEC 9899:2011)说:
8通过限制限定指针访问的对象与该指针有特殊关联。这种关联在下面的6.7.3.1中定义,要求对该对象的所有访问都直接或间接地使用该特定指针的值。 135)限制限定符的预期用途(如寄存器)存储类)是为了促进优化,并且从构成符合程序的所有预处理翻译单元中删除限定符的所有实例不会改变其含义(即,可观察的) 行为)。
135)例如,将
malloc
返回的值赋给单个指针的语句建立了这个 分配的对象和指针之间的关联。
第6.7.3.1节 restrict
的正式定义说:
1让
D
成为普通标识符的声明,它提供了一种将对象P
指定为类型T
的限制限定指针的方法。2如果
D
出现在一个区块内且没有存储类extern
,请让B
表示该区块。如果D
出现在函数定义的参数声明列表中,则让B
表示关联的块。否则,让B
表示main
的块(或在独立环境中程序启动时调用的任何函数块)。3在下文中,指针表达式
E
被称为基于对象P
if(在B
执行的某个序列点,在E
的评估之前1}})修改P
以指向它先前指向的数组对象的副本将改变E
的值。 137)注意''based' '仅针对具有指针类型的表达式定义。4在
B
的每次执行期间,让L
为基于&L
P
的左值。如果L
用于访问其指定的对象X
的值,并且X
也被修改(通过任何方式),则以下要求适用:T
不得具有合格资格。用于访问X
值的每个其他左值也应具有基于P
的地址。出于本子条款的目的,修改X
的每次访问也应被视为修改P
。如果P
被赋予指针表达式E
的值,该指针表达式基于与块P2
相关联的另一个受限指针对象B2
,然后B2
的执行将在B
的执行,或B2
的执行应在转让之前结束。如果不满足这些要求,则行为未定义。5这里
B
的执行意味着程序执行的一部分对应于具有与B
相关联的标量类型和自动存储持续时间的对象的生命周期。137)换句话说,
E
取决于P
本身的值,而不是通过P
间接引用的对象的值。例如,如果标识符p
具有类型(int **restrict
),则指针表达式p
和p+1
基于p
指定的受限指针对象,但指针表达式*p
和p[1]
不是。
这似乎允许你展示的代码。指针引用是基于'受限制的指针以及该部分允许的那些。