我正在浏览一些文档和问题/答案,并看到它提到.我读了一个简短的描述,声明它基本上是程序员的承诺,指针不会用于指向其他地方.
任何人都可以提供一些现实案例,其值得实际使用吗?
我知道它提高了可读性并使程序不易出错,但它提高了多少性能?
在旁注中,参考和const指针之间的主要区别是什么?我会假设它们以不同的方式存储在内存中,但是如何呢?
我试图了解何时何时不在restrictC中使用关键字以及在什么情况下它提供了实实在在的好处.
在阅读" 揭秘限制关键字 "(提供一些关于使用的经验法则)之后,我得到的印象是,当函数通过指针时,它必须考虑指向的数据可能重叠的可能性(别名)将任何其他参数传递给函数.给定一个功能:
foo(int *a, int *b, int *c, int n) {
for (int i = 0; i<n; ++i) {
b[i] = b[i] + c[i];
a[i] = a[i] + b[i] * c[i];
}
}
Run Code Online (Sandbox Code Playgroud)
编译器必须c在第二个表达式中重新加载,因为可能b并c指向相同的位置.b在a出于同样的原因加载之前,它还必须等待存储.然后它必须等待a存储并且必须重新加载b并且c在下一个循环的开始.如果你这样调用函数:
int a[N];
foo(a, a, a, N);
Run Code Online (Sandbox Code Playgroud)
然后你就可以看到为什么编译器必须这样做了.使用restrict有效地告诉编译器你永远不会这样做,这样它就可以在存储之前丢弃冗余负载c和负载.ab
在另一篇SO帖子中,Nils Pipenbrinck提供了这个场景的工作示例,展示了性能优势.
到目前为止,我已经收集到了一个好主意,使用restrict指针传递给不会内联的函数.显然,如果代码是内联的,编译器可以发现指针不重叠.
现在,这里的事情开始让我变得模糊.
在Ulrich Drepper的论文中," 每个程序员应该了解内存 ",他发表声明称,"除非使用限制,所有指针访问都是混淆的潜在来源",并且他给出了一个子矩阵矩阵的特定代码示例.用途restrict.
但是,当我编写他的示例代码时,无论有没有, …
例如,请考虑以下结构:
struct S {
int a[4];
int b[4];
} s;
Run Code Online (Sandbox Code Playgroud)
写作s.a[6]并期望它等于是合法的s.b[2]吗?就个人而言,我觉得它必须是C++中的UB,而我不确定C.但是,我没有找到任何与C和C++语言相关的内容.
更新
有几个答案建议确保字段之间没有填充以使代码可靠地工作的方法.我想强调的是,如果这样的代码是UB,那么填充缺失是不够的.如果它是UB,那么编译器可以自由地假设访问S.a[i]和S.b[j]不重叠,并且编译器可以自由地重新排序这样的存储器访问.例如,
int x = s.b[2];
s.a[6] = 2;
return x;
Run Code Online (Sandbox Code Playgroud)
可以转化为
s.a[6] = 2;
int x = s.b[2];
return x;
Run Code Online (Sandbox Code Playgroud)
总是回来2.
我听说有英特尔在线书籍描述了特定汇编指令所需的CPU周期,但我无法找到它(经过努力).有人能告诉我如何找到CPU周期吗?
下面是一个例子,在下面的代码中,mov/lock是1个CPU周期,xchg是3个CPU周期.
// This part is Platform dependent!
#ifdef WIN32
inline int CPP_SpinLock::TestAndSet(int* pTargetAddress,
int nValue)
{
__asm
{
mov edx, dword ptr [pTargetAddress]
mov eax, nValue
lock xchg eax, dword ptr [edx]
}
// mov = 1 CPU cycle
// lock = 1 CPU cycle
// xchg = 3 CPU cycles
}
#endif // WIN32
Run Code Online (Sandbox Code Playgroud)
顺便说一句:这是我发布的代码的URL:http://www.codeproject.com/KB/threads/spinlocks.aspx
据我所知,GCC支持C++中的所有C99功能.但是如何在C++代码中处理C99严格别名?
我知道在不相关的类型之间使用C转换进行转换不是严格别名安全的,并且可能生成错误的代码,但是C++呢?由于严格别名不是C++标准的一部分(这是正确的吗?),GCC必须指定语义本身.
我想,const_cast与static_cast相关类型之间的演员阵容,因此他们是安全的,而reinterpret_cast可以打破严格走样规则.
这是正确的理解吗?