好的,让我们从最明显的解决方案开始:
memcpy(Ptr, (const char[]){'a', 'b'}, 2);
Run Code Online (Sandbox Code Playgroud)
调用库函数的开销很大。编译器有时不优化它,我不会依赖编译器优化,但即使 GCC 很聪明,如果我将程序移植到带有垃圾编译器的更奇特的平台上,我不想依赖它。
所以现在有一个更直接的方法:
Ptr[0] = 'a';
Ptr[1] = 'b';
Run Code Online (Sandbox Code Playgroud)
它不涉及任何库函数的开销,而是进行两个不同的分配。第三,我们有一个双关语:
*(uint16_t*)Ptr = *(uint16_t*)(unsigned char[]){'a', 'b'};
Run Code Online (Sandbox Code Playgroud)
如果遇到瓶颈,我应该使用哪一种?在 C 中只复制两个字节的最快方法是什么?
问候,
汉克·萨里
您建议的方法中只有两种是正确的:
memcpy(Ptr, (const char[]){'a', 'b'}, 2);
Run Code Online (Sandbox Code Playgroud)
和
Ptr[0] = 'a';
Ptr[1] = 'b';
Run Code Online (Sandbox Code Playgroud)
在 X86 GCC 10.2 上,两者都编译为相同的代码:
mov eax, 25185
mov WORD PTR [something], ax
Run Code Online (Sandbox Code Playgroud)
由于as-if 规则,这是可能的。
由于好的编译器可以确定这些是相同的,因此请使用更容易在您的 cse 中编写的编译器。如果您要设置一两个字节,请使用后者,如果有几个使用前者或使用字符串而不是复合文字数组。
你推荐的第三个
*(uint16_t*)Ptr = *(uint16_t*)(unsigned char[]){'a', 'b'};
Run Code Online (Sandbox Code Playgroud)
在使用 x86-64 GCC 10.2 时也编译为相同的代码,即在这种情况下它的行为相同。
但此外它还有2-4 个未定义行为点,因为它有两次严格的别名违规和两次,再加上可能在源和目标上未对齐的内存访问。未定义的行为并不意味着它不能像您预期的那样工作,但也不意味着它必须按您的预期工作。行为未定义。它可能无法在任何处理器上工作,包括 x86。为什么你会如此关心一个糟糕的编译器的性能,以至于你会编写无法在一个好的编译器上运行的代码?!
归档时间: |
|
查看次数: |
141 次 |
最近记录: |