c - 在 C 中复制两个相邻字节的最快方法是什么?
问题描述
好的,让我们从最明显的解决方案开始:
memcpy(Ptr, (const char[]){'a', 'b'}, 2);
调用库函数的开销很大。编译器有时不会优化它,我不会依赖编译器优化,但即使 GCC 很聪明,如果我将程序移植到带有垃圾编译器的更奇特的平台上,我也不想依赖它。
所以现在有一个更直接的方法:
Ptr[0] = 'a';
Ptr[1] = 'b';
它不涉及库函数的任何开销,而是进行两个不同的分配。第三,我们有一个双关语:
*(uint16_t*)Ptr = *(uint16_t*)(unsigned char[]){'a', 'b'};
如果遇到瓶颈,我应该使用哪一个?在 C 中只复制两个字节的最快方法是什么?
问候,
Hank Sauri
解决方案
您建议的方法中只有两种是正确的:
memcpy(Ptr, (const char[]){'a', 'b'}, 2);
和
Ptr[0] = 'a';
Ptr[1] = 'b';
在 X86 GCC 10.2 上,两者都编译为相同的代码:
mov eax, 25185
mov WORD PTR [something], ax
由于as-if 规则,这是可能的。
由于一个好的编译器可以发现它们是相同的,因此请使用更容易在您的 cse 中编写的编译器。如果要设置一个或两个字节,请使用后者,如果有多个使用前者或使用字符串而不是复合文字数组。
你建议的第三个
*(uint16_t*)Ptr = *(uint16_t*)(unsigned char[]){'a', 'b'};
使用 x86-64 GCC 10.2 时也会编译为相同的代码,即在这种情况下它的行为相同。
但除此之外,它还有2-4 个未定义行为点,因为它有两次严格的别名违规和两次,再加上源和目标上可能存在未对齐的内存访问。未定义的行为并不意味着它不能按您的预期工作,但也不意味着它必须按您的预期工作。行为未定义。它可能无法在任何处理器上运行,包括 x86。为什么你会如此关心一个糟糕的编译器的性能,以至于你会编写无法在一个好的编译器上运行的代码?!
推荐阅读
- mysql - Laravel 基于另一列对两列进行求和/减法
- reactjs - 来自 Redux 存储的数据来晚了,所以它不会填满 AG 网格表/反应钩子
- powershell - PowerShell 打开 .msi 而不是将路径保存到变量中
- string - Tosca 谜题 41036 用 RBFW 解决(标题:TABLE SEARCH):code isseu= Strip string does not strip all the characters
- autodesk-forge - 查看器中的 IFC 模型没有模型问题
- android - 三星 A10 android 11 如何从我的应用程序以编程方式创建其他应用程序固定快捷方式
- php - 在laravel 8的外部js文件中设置ajax url
- facebook-graph-api - Instagram 故事图 api
- c - C中的这个运算符是什么?
- python - 从 pandas 填充一个 nd 维 numpy 数组