0

考虑这两个函数:

void foo(char * __restrict localPtr)
{
    // some work with localPtr
}

void bar(char * __restrict ptr)
{
    // some work with ptr
    foo(_ptr);
    // some other work with ptr
}

正如ptr在 中声明__restrict的那样bar,打电话foo()危险吗?localPtr所谓危险,我的意思是重叠指向的内存区域ptr。对此有何指导方针?

4

1 回答 1

3

restrict限定符意味着被调用函数访问传入内存的唯一方法是通过localPtrfoo指针;那段记忆没有别名。这可能使优化器能够生成更好的代码,因为它不必担心另一个指针也会改变数据。

在这种情况下,以及在大多数其他情况下,restrict限定符对您(进行调用的程序员)承担了责任,以确保您遵守“无别名”要求。

上面的代码没有明显的危险。

请注意,大多数情况下,在使用时,参数列表中有多个指针restrict。从 C 标准,比较:

void *memcpy(void *restrict s1, const void *restrict s2, size_t n);
void *memmove(void *s1, const void *s2, size_t n);

第一个 ( memcpy()) 表示内存块不能重叠[s1 .. s1+n-1][s2 .. s2+n-1]如果它们实际上重叠,您将获得未定义的行为。第二个 ( memmove()) 没有强加该要求。


但不是调用foo()创建另一个更改数据的指针吗?

是的,不,有点……但大多不是。

in 中的指针foo()当然是传递给 的bar(),但是在bar()运行时,唯一bar()可以获取内存的方法是通过它传递的指针。因此bar(),可以在假设它正在使用的内存没有别名的情况下进行编译。

当编译器正在处理foo()时,它知道(确保)在计算参数之后bar()和调用函数之前有一个序列点,并且在函数返回时有另一个序列点。它知道数据可能已被修改,bar()因为它没有被传递const char *。因此,它将生成代码来解释这些可能性。但是,编译器也知道唯一foo()可以访问所寻址的内存的方法localPtr是通过localPtr(这就是restrict所说的),并且它可以基于该假设继续进行。

因此,在被调用时存在指针的第二个副本,但它没有以任何方式bar()违反规则。restrict

于 2012-10-06T15:16:43.980 回答