c - 将限制指针分配给非限制指针的语义是什么?
问题描述
以下假设代码是否正确(注释中的假设是否成立)?还是有UB?
#define N 1 // what if it's 0?
void foo(int *x, int * restrict y) {
*x = 42;
*y = 0;
// compiler can assume *x is still 42.
{
int *a = y + N;
*a = 123;
// compiler can no longer assume *x is 42.
} // does the new scope matter in this case?
}
解决方案
// compiler can no longer assume *x is 42.
我认为这种说法没有根据。
// does the new scope matter in this case?
不,restrict 的规则涵盖块B,对于在函数参数中声明的限制限定指针,它是定义函数的块。该块 B 中的该块是B的一部分。
的定义restrict
在 C 2018 6.7.3.1 中给出。第 1 段说:
令D是一个普通标识符的声明,它提供了一种将对象P指定为类型T的限制限定指针的方法。
int * restrict y
是普通标识符“<code>y”的声明Dy
,并指定对象Pint
,它是指向(类型T )的限制限定指针。
第 2 段说:
...如果D出现在函数定义的参数声明列表中,让B表示关联的块...</p>
所以B是定义函数的块。
第 3 段说:
在下文中,指针表达式E被称为基于对象P如果(在执行B的某个序列点,在评估E之前)修改P以指向它以前指向的数组对象的副本将更改E的值。)请注意,“基于”仅针对具有指针类型的表达式定义。
所以,之后int *a = y + N;
,a
是基于y
因为y
在此初始化之前修改a
会更改 的值a
,即使y
更改为指向数组的副本。
第 4 段说:
在每次执行B期间,令L为基于P具有&L的任何左值。如果L用于访问它指定的对象X的值,并且X也被修改(以任何方式),则适用以下要求: ... 用于访问X值的每个其他左值也应基于其地址在P上……</p>
*a
是一个具有&L基于的左值L,因为是,我们知道是基于。y
&*a
a
a
y
然后,在 中*a = 123;
,这个L用于访问它指定的对象,并且该对象被修改。所以要求必须适用:用于访问对象的每个其他左值也应基于y
.
所以,如果*x
还访问了 指定的对象*a
,那就违反了上面的要求,因为&*x
不是基于y
. x
作为单独的参数传递,更改 的值y
不会更改 的值x
,因此x
和&*x
不基于y
。
由于编译器有权期望满足要求,因此它可能会假设*a = 123;
不会改变*x
。
推荐阅读
- ethereum - 在以太坊中升级智能合约
- javascript - 生成多个随机字母来创建解密效果?
- javascript - 类文字中的自引用,并使用 DOM 元素进行实例化
- r - 无法转换为 POSIXct (R)
- c++ - Raspberry Pi 上预装的 opencv 库的问题
- java - jdbc 无法与 java 连接
- php - 从 wordpress 网站中删除 type="text/javascript"
- clojure - 在 Clojure 中构建 CLI 脚本
- graph - 为什么在 Neo4j 中通过 CREATE 或 MERGE 查询创建多个节点
- node.js - 在使用 Mocha 测试之前清除集合