调用函数并将其传递给限制限定指针是危险的吗?

时间:2012-10-06 15:06:30

标签: c++ restrict-qualifier

考虑这两个功能:

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__restrictbar声明为foo(),是否正在调用localPtr危险?危险,我的意思是ptr指向的记忆区域与{{1}}重叠。有关这方面的指导原则是什么?

1 个答案:

答案 0 :(得分:2)

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

在这种情况下,以及在大多数其他情况下,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()创建另一个正在更改数据的指针吗?

是,否,排序......但主要是否。

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

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

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