【发布时间】:2020-02-25 09:58:17
【问题描述】:
我有这段代码,但我想知道为什么编译器不将两个字符与 16 位比较进行比较。
inline bool beginswith (char c0, char c1, const char* s) {
return (s[0] == c0) & (s[1] == c1);
}
bool test(const char* s) {
return beginswith('0', 'x', s);
}
我希望我的Godbolt 链接(test 和 test2)中的两个版本能够编译为等效指令。有什么我遗漏的,因为这似乎是一个非常微不足道的优化。
编辑:我希望编译器进行这种优化的原因是我可以编写没有未定义行为的可移植代码,并且仍然可以获得完整的性能。
【问题讨论】:
-
我已经设法使 GCC 输出与
char const b[]{c0, c1}; return !std::memcmp(b, s, sizeof b);相同的程序集。 MSVC 未分阶段。 -
我的猜测是,编译器不会做这个优化,因为这里
*(const short*)s == (c0 | (c1 << 8));可能会发生未对齐的访问,与字节访问版本相比,这可能会产生巨大的性能损失 -
@Ayxan:没关系。允许编译器定义并因此利用 UB;只是程序员不被允许。
-
beginswith2是未定义的行为。根据机器的字节序,您可以将c0/c1与 s...的 msb/lsb 进行比较... -
const char* s = "_x"; beginswith('x', 'X', s+1);char 访问s+1比short访问更快(在硬件级别,在某些拱门上)。输出组装的差异可能反映了这种差异。
标签: c++ performance optimization