C restrict关键字/限定符是否可以通过多个级别的指针间接传递?

例如,给定以下片段:

struct Bar {
    int b;
};

struct Foo
{
    struct Bar* bar;
};

int examineFoos(struct Foo* restrict foo1, struct Foo* restrict foo2)
{
    foo1->bar->b = 1;
    return foo2->bar->b;
}

int main(void)
{
    struct Bar bar = { 0 };
    struct Foo foo1 = { .bar = &bar };
    struct Foo foo2 = { .bar = &bar };
    int val = examineFoos(&foo1, &foo2);
    return val;
}

这是否会调用未定义的行为并可以调用val == 0,因为它在访问bar时违反了restrict,或者这是有效代码,并且我们总是得到val == 1,因为restrict没有通过bar指针传递应用?

推荐答案

foo1foo2restrict个资格不会对foo1->barfoo2->bar指出的 struct 的使用施加任何限制,如下所示.

C 2018 6.7.3.1 4中规定了对计划施加restrict的要求.这些要求仅适用"如果L用于访问其指定的对象X的值,并且X也被修改(通过任何方式)",其中L是左值,对于该左值,&L基于P,该P已被指定为类型T的限制限定指针.Based在6.7.3.1中指定 3:

在接下来的内容中,如果(在判断E之前执行B的某个序列点)修改P以指向其先前指向的数组对象的副本,则指针表达E被称为对象P上的based.

限制合格指针为foo1foo2.考虑foo1->barfoo2->bar是否可以基于foo1foo2.换句话说,如果Efoo1->barfoo2->bar,如果进行上述修改,它的值会改变吗?

假设在examineFoos的主体(块B)中的各个点,我们制作foo1foo2所指向的 struct 的副本,然后更改foo1foo2以指向相应的副本.这次干预后foo1->bar的值会和之前一样吗?是的,因为foo1->bar的值是由代表它的字节决定的,并且这些字节已被复制.同样,foo2->bar也将具有相同的值.

因此,foo1->barfoo2->bar不是基于foo1foo2,因此restrict的规范不会对使用它们来访问它们指向的对象施加任何要求.

C++相关问答推荐

try 使用libusb控制音量时LIBUSB_WRIGHT_PIPE

Malloc(sizeof(char[Length]))是否不正确?

警告:C++中数组下标的类型为‘char’[-Wchar-subpts]

为什么sscanf不能正确地从这个字符串格式中提取所有数字?

X86/x64上的SIGSEGV,由于原始内存访问和C中的DS寄存器之间的冲突,在Linux上用TCC编译为JIT引擎

当输入负数时,排序算法存在问题

C-使用指针返回修改后的整数数组

限制不同类型的限定符

为什么将函数名括在括号中会禁用隐式声明?

链接到底是如何工作的,我在这里到底做错了什么

条件跳转或移动取决于未初始化值(S)/未初始化值由堆分配创建(Realloc)

为什么我无法访问C语言中的文件

在C中使用无符号整数模拟有符号整数

在下面的C程序中,.Ap0是如何解释的?

未使用sem_open正确初始化信号量

C语言中的指针和多维数组

通过char*访问指针的对象表示是未定义的行为吗?

函数指针作为函数参数 - 应该使用 const 吗?

为什么<到达*时不会转换为>?

当循环变量在溢出时未定义时,可以进行哪些优化?