如何理解 C/C++ 中的 指针别名(pointer alias)、restrict、const 的关系呢?
背景
最近在写点 C,发现以前一直没注意到 指针别名(pointer alias)、restrict 这些东西。
初步看了看,感觉以后碰指针要更烧脑了,否则动不动就会遇到 UB 代码。。想来讨论讨论,弄弄清楚。
比如,这个快速求平方根的代码,居然是 UB 的。。
float Q_rsqrt( float number ) { long i; float x2, y; const float threehalfs = 1.5F; x2 = number * 0.5F; y = number; i = * ( long * ) &y; // evil floating point bit level hacking i = 0x5f3759df - ( i >> 1 ); // what the fuck? y = * ( float * ) &i; y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed return y; }
个人理解
按我目前理解,一个指针经 restrict 修饰后,它(可能经过指针运算后)指向的对象不会有其它别名。
修改一个对象,会污染它所有相同/兼容/字符类型的别名,使得下一次使用它们时,需要重新读取。
疑惑
-
const int * restrict p有意义吗?cppreference - restrict 类型限定符 说(大意,个人理解):
每次执行声明有
restrict的指针P的代码块时(如int func (int * restrict P) {...}),如果通过P(直接或间接地)修改了某个对象,后续都必须通过P来读写该对象,否则行为未定义。由于只读的
p无法被写入,所以restrict体现不出作用? -
两个预计不会重叠的内存块,可以只指定一次
restrict来达到目的吗?比如,
memcpy的原型:void* memcpy( void *restrict dest, const void *restrict src, size_t count )可以去掉
src的restrict,只保留dest的吗?若如此,似乎也能表达出:dest的内存块是独占的,src自然不会与dest有重叠 -
对
restrict指针realloc时,需要有什么特殊处理吗?








