我想用它来比较性能关键代码中的短字符串(4到8个字符长)。我想将它们转换为整数值并比较这些值而不是比较字符串:
const char* str = "abcdefgh";
uint64_t num = *reinterpret_cast<const uint64_t*>(str);
在不检查str
指针的对齐情况下,将uint64_t
强制转换为char*
是否安全?我只在ARM和Intel CPU上使用该代码,32位和64位。
如果行为定义良好且强制转换是安全的,那么当指针未对齐到8个字节时,我是否应该期待性能下降?
您是否有其他建议以非常快的方式执行此操作?
答案 0 :(得分:2)
此代码将产生不正确的行为,因为null终止符后面的字节内容不是字符串的一部分。例如,考虑字符串:
char str1[8] = { 't', 'e', 's', 't', 0, 0, 0, 1 };
char str2[8] = { 't', 'e', 's', 't', 0, 0, 0, 2 };
两个字符串都具有值"test"
,但将它们作为整数进行比较会说它们是不同的,因为字符串末尾后面的一个字节是不同的。此外,如果字符串从分配的内存页的末尾开始少于8个字节,则尝试从中读取整数将导致段错误。
使用strcmp()
来比较字符串。它已经非常快,并且会给出正确的结果。
答案 1 :(得分:1)
您提议的内容不可移植,实际上违反了C ++严格别名规则。这是未定义的行为。
来自标准:第3.10.10节
如果某个程序试图通过以下某种类型之外的 glvalue 访问对象的存储值,则行为未定义:
- 对象的动态类型,
- 对象的动态类型的cv限定版本,
- 与对象的动态类型相似的类型(如4.4中所定义)
- 与对象的动态类型对应的有符号或无符号类型的类型
- 与对象的动态类型的cv限定版本对应的有符号或无符号类型的类型,
- 聚合或联合类型,包括其元素或非静态数据成员中的上述类型之一(递归地,包括子聚合或包含联合的元素或非静态数据成员),
- 一种类型,它是对象动态类型的(可能是cv限定的)基类类型,
char
或unsigned char
类型。
最可靠,最便携的方法就是使用strcmp()
。
答案 2 :(得分:0)
你可以可靠地(见下面的评论)&#34; cast&#34;一串字符到这样的整数。您需要使用按位运算符,如下所示:
Using bitwise operators in C++ to change 4 chars to int
(当然,你只能将四个字符组合成一个32位整数。)
但我不确定你为什么要假设&#34;雾化&#34;像这样的字符串将比调用strcmp()更快,strcmp()在大多数C库的汇编代码中实现。
答案 3 :(得分:0)
尝试双向运行代码并查看。您可能会发现它们以相同的速度运行!这种测试通常是内存带宽有限的,因此循环中执行的指令数量几乎不重要。
重要的是要注意,这只有在字符串值填充了整数大小的空值时才有效,您将其表示为对不同答案的注释。
至于它是否是合法的C ++,请参阅Aliasing `T*` with `char*` is allowed. Is it also allowed the other way around?