重置/包装 C/C++ 中的变量(环缓冲区指针)
Reseting/wraping around a variable in C/C++ (ringBuffer Pointer)
我正在编程一些环形缓冲区,这个问题多次出现在我面前。
假设我们有一个计数器,我们需要在一定计数后重置。 我看到了几个环形缓冲区的例子(主要是音频,环绕 r/w 指针),它们这样做:
x++;
if (x == SOME_NUMBER ){ // Reseting counter
x -= x;
}
这样做有什么区别/偏好吗:
x++;
if (x == SOME_NUMBER ){ // Reseting counter
x = 0;
}
?
这个问题几乎适用于所有类型的变量重置。就我而言,除了环形浮子之外,我还重置了一个做平均值的计数器,所以在我做了所有措施后,我重置了那个计数器。
除了结果可能相同(x 重置为零)这一事实之外,一种方法和另一种方法之间可能存在一些差异。有什么偏好吗?
考虑那些稍微修改过的片段版本
void f(int n)
{
int x = 0;
for (;;)
{
++x;
if (x == n ) { // Reseting counter
x -= x;
}
// Ending condition to avoid UB
if ( x == 42 )
return;
}
}
void g(int n)
{
int x = 0;
for (;;)
{
++x;
if (x == n ) {
x = 0;
}
if ( x == 42 )
return;
}
}
如果您查看生成的程序集(例如,使用编译器资源管理器),您会注意到现代优化编译器如何利用 as-if 规则。
Clang(带-O2
)为这两个函数生成相同的机器代码。它使用
xor eax, eax
将零加载到寄存器中,然后
cmove ecx, eax
在需要时"重置"另一个寄存器。
gcc 只是创建f()
然后g()
成为
jmp f(int)
可是
有什么偏好吗?
一个常见的准则是编写更具可读性和可维护性的代码,并仅在对其进行分析后探索可能的优化。
在大多数情况下,我会使用x = 0;
版本,因为它可以更好地传达意图,恕我直言。我只能想到采用x -= x;
几个理由:
- 它不依赖于"幻数"。但是,我的片段中的
42
文字就是这种情况,0
是一个例外情况。 - 它不需要任何隐式转换。考虑任何
x
不是int
的情况。 - 可能有一些架构/工具链实际上提供了更快的代码。我想不出任何,但这无关紧要。
区别在于操作的数量:x -= x
是减法和赋值,而x = 0
只是赋值。除了 CPU 周期数之外,如果可从其他线程访问x
,这会影响行为。
一个简单的分配x = 0
也更清晰,IMO也是如此。
相关文章:
- 将字符缓冲区强制转换为函数指针
- 将指针作为缓冲区传递到第一个字符串元素
- 将constexpr字节数组与缓冲区的一部分(指向数据的指针)进行比较
- char p[0]表示自动分配的缓冲区还是安全指针
- 指针符号在参数规范中表示什么,例如:(char16 *缓冲区,int32 大小)?C++
- OpenGL:使用指向静态数据的指针数组传递缓冲区数据
- 重置/包装 C/C++ 中的变量(环缓冲区指针)
- 将 char* 推送到矢量时出现问题,但在每次迭代后,它会将指向相同值缓冲区的指针添加到矢量中
- 返回指向矢量数据的指针,而不复制缓冲区和内存泄漏
- memcpy指向炭缓冲区的指针
- 来自 2 个指针的组合缓冲区,无需复制
- 来自指针向量的OpenGL阵列缓冲区
- C++:使用std::ifstream读取二进制文件后删除缓冲区/指针时发生访问冲突
- 如何将一个缓冲区指针的内容复制到另一个缓冲区指针
- 正在将缓冲区/指针设置为null
- 将额外的字节填充到要通过网络发送的flatbuffer的缓冲区指针
- 从缓冲区指针计算堆栈中的返回地址
- MPI_scatter:缓冲区指针无效
- MPI_Pack:无效缓冲区指针
- GetIndices()会在CreateIndexBuffer()和SetIndices()之后返回相同的缓冲区指针吗?