#include <cstdint>
#include <cstring>
struct Point {
std::int32_t x, y;
};
[[nodiscard]]
bool naiveEqual(const Point &a, const Point &b) {
return a.x == b.x && a.y == b.y;
}
[[nodiscard]]
bool optimizedEqual(const Point &a, const Point &b) {
// Why can't the compiler produce the same assembly in naiveEqual as it does here?
std::uint64_t ai, bi;
static_assert(sizeof(Point) == sizeof(ai));
std::memcpy(&ai, &a, sizeof(Point));
std::memcpy(&bi, &b, sizeof(Point));
return ai == bi;
}
[[nodiscard]]
bool optimizedEqual2(const Point &a, const Point &b) {
return std::memcmp(&a, &b, sizeof(a)) == 0;
}
[[nodiscard]]
bool naiveEqual1(const Point &a, const Point &b) {
// Let's try avoiding any jumps by using bitwise and:
return (a.x == b.x) & (a.y == b.y);
}
但令我惊讶的是,只有带有memcpy
或memcmp
的代码会被gcc转换为单个64位比较。为什么?(https://godbolt.org/z/ap1ocs)
对优化器来说,如果我在四个字节的连续对上检查相等性,这与在所有八个字节上进行比较是一样的,难道不是很明显吗?
避免将两个部分单独进行布尔化的尝试会更有效地编译(少了一个指令,没有对EDX的错误依赖),但仍然有两个单独的32位操作。
bool bithackEqual(const Point &a, const Point &b) {
// a^b == 0 only if they're equal
return ((a.x ^ b.x) | (a.y ^ b.y)) == 0;
}
GCC和Clang在通过值传递结构时都有相同的漏选优化(因此A
在RDI中,B
在RSI中,因为x86-64 System V的调用约定就是这样将结构打包到寄存器中的):https://godbolt.org/z/v88a6s。memcpy/memcmp版本都编译为CMP rdi、RSI
/seteal
,但其他版本执行单独的32位操作。
struct alignas(uint64_t)point
在参数位于寄存器中的by-value情况下仍然很有帮助,为GCC优化了两个naiveEqual版本,但不是bithack异或/或。(https://godbolt.org/z/ofga1f)。这给了我们关于GCC内部的任何提示吗?对齐没有帮助。
如果您“修复”对齐,则所有的汇编语言输出都是相同的(带有GCC):
struct alignas(std::int64_t) Point {
std::int32_t x, y;
};
演示
需要注意的是,一些正确/合法的方法(如类型双关语)是使用memcpy
,因此在使用该函数时进行特定的优化(或更加积极)似乎是合乎逻辑的。
为什么运算符只应该是4个字节却生成12个字节?当我引用变量时,这只是引用数组第一个索引的内存地址。实际上,我打印了第一个索引的内存地址,并将其与进行了比较,它们产生了相同的内存地址结果,这证实了它们都引用了数组的第一个索引,但是“array”产生了12个字节,而产生了4个字节。
问题内容: 为什么需要添加“ L”字母以获得正确的长值?还有什么其他价值呢? 问题答案: 你的第一个值实际上是一个long(因为是,并且是,所以带值的值的结果就是一个long值。 但是第二个值是一个整数(因为你仅将一个值与一个值混用。所以结果将是一个整数。现在,所获得的结果超出了整数的实际范围。因此,在分配给该变量之前,被截断以适合有效的整数范围。 查看以下打印语句: 当你运行上面的代码时: 输出
下面的代码通过使用特征向量作为容器或简单的C数组来实现相同的计算。它产生一个封闭的但不是位到位等效的结果。 最后的数学运算是。
代码 产出(如预期) 1.post increment运算符()在表中具有最高的优先级。因此它肯定会在赋值运算符()之前执行。根据post增量规则,变量的值只有在执行该语句之后才会增加。 参见有rvalue 3,而不是变量本身,对吗?但是如果它带来了一个具有lvalue的变量,那么5将插入其中,在语句结束后,它的值将是6。这有什么问题,为什么做不到?
“...如果这不可行,RFC4122建议使用命名空间变体,如类型5 UUID。” 我计划使用Java生成UUID,并引用了API https://docs.oracle.com/javase/8/docs/API/Java/util/UUID.html 通过维基百科:
我使用mapstruct在两个Calses之间进行映射:CandidateDTO和CandidateDTO。 我在这里的问题是,当映射时,所有DTO字段都为空,因为没有生成映射字段。 请帮忙。