两者中哪一个更快:?
1
char* _pos ..;
short value = ..;
*((short*)_pos = va;
2
char* _pos ..;
short value = ..;
memcpy(_pos, &value, sizeof(short));
答案 0 :(得分:8)
与所有“哪个更快?”一样问题,你应该对它进行基准测试,以便亲眼看看。如果重要的话,那就问问为什么然后挑选你想要的东西。
在任何情况下,您的第一个示例在技术上是 未定义的行为 ,因为您违反了严格别名。因此,如果您必须选择没有基准测试,请选择第二个。
要回答实际问题,速度更快可能取决于pos
的对齐方式。如果它正确对齐,那么1可能会更快。如果没有,则2可能会更快,具体取决于编译器如何优化它。 (如果硬件不支持错位访问,则1甚至可能崩溃。)
但这都是猜测工作。你确实需要对它进行基准测试才能确定 至少,您应该查看已编译的程序集:
: *(short *)_pos = value;
mov WORD PTR [rcx], dx
VS
: memcpy(_pos, &value, sizeof(short));
mov WORD PTR [rcx], dx
在这种情况下(在MSVC中)显示具有默认优化的完全相同的程序集。所以你可以期待性能相同。
答案 1 :(得分:4)
gcc
的优化级别为-O1
或更高,以下两个函数在x86上编译为完全相同的机器代码:
void foo(char *_pos, short value)
{
memcpy(_pos, &value, sizeof(short));
}
void bar(char *_pos, short value)
{
*(short *)_pos = value;
}
答案 2 :(得分:2)
编译器可以以相同的方式实现它们
如果它天真地做,分配会更快。
出于任何实际目的,它们都会立即完成,您无需担心。
另请注意,您可能存在对齐问题(_pos
可能无法在2个字节上对齐,这可能会在某些处理器上崩溃),并输入惩罚问题(编译器可能会假设_pos
指向未更改,因为您使用short *
)编写。
答案 3 :(得分:0)
重要吗?可能是第一种情况会为您节省一些周期(取决于编译器的复杂程度和优化)。但值得注意的是可读性和可维护性吗?
由于过早优化而引入了许多错误。您应该首先确定瓶颈,如果这个任务是瓶颈 - 对每个选项进行基准测试(照顾其他人已经提到的对齐和其他问题)。
答案 4 :(得分:0)
问题是依赖于实现。在实践中,除了复制sizeof(短)字节之外什么都不做,如果一个人要慢一点,那就是memcpy。对于相当大的数据集,如果一个更快,它通常将是memcpy。
正如所指出的,#1调用未定义的行为。
我们可以看到,简单的赋值肯定更容易读写,并且比两者都更容易出错。清晰度和正确性应该首先出现,即使在性能关键领域也是如此,原因很简单,优化正确的代码比修复优化的错误代码更容易。如果这确实是一个C ++问题,那么需要这样的代码(将类型系统推平到x射线并围绕位进行推广的强制转换或memcpy)应该是非常非常罕见的。
答案 5 :(得分:0)
如果您确定不存在对齐问题,并且您确实发现这是一个瓶颈情况,请继续执行第一步。
如果您不熟悉调用memcpy,请执行以下操作:
*pos = static_cast<char>(value & 0xff );
*(pos+1) = static_cast<char>(value >> 8 );
虽然如果你打算这样做,那么使用无符号值。
上面的代码也确保你得到小端。 (如果你想要big-endian,显然可以改变作业的顺序)。如果数据作为某种二进制blob传递,你可能想要一致的字节序,我猜,这是你想要创建的。
如果要创建二进制blob,您可能希望使用Google协议缓冲区之类的内容。还有boost :: serialize,包括二进制序列化。
答案 6 :(得分:0)
您可以使用union来避免破坏别名规则并调用函数:
union {
char* c;
short* s;
} _pos;
short value = ...
_pos->s = value;