败犬日报 2025-11-17
1. 一个结构体因为对齐多出来的空地方,如果 memcpy 一下是不是未定义行为
对于可平凡复制类型,不是。
这个操作还是很常见的,当然常见不代表不是 UB,所以还要翻法律条文 https://en.cppreference.com/w/cpp/language/object.html:
For TriviallyCopyable types, value representation is a part of the object representation, which means that copying the bytes occupied by the object in the storage is sufficient to produce another object with the same value (except if the object is a potentially-overlapping subobject, or the value is a trap representation of its type and loading it into the CPU raises a hardware exception, such as SNaN ("signalling not-a-number") floating-point values or NaT ("not-a-thing") integers). 翻译:对于可平凡复制类型,它的值表示是对象表示的一部分,这意味着复制该对象在存储中所占据的字节就足以产生另一个具有相同值的对象(除非这个值是该类型的一个“陷阱表示”,将它读取到 CPU 中会产生一个硬件异常,就像浮点数的 SNaN(“Signaling NaN 发信非数”)或整数的 NaT(“Not a Thing 非事物”))。
2. 调用函数怎么编译成了 jmp 而不是 call
例如 GCC -O2 编译:
void foo(int* a, const int* b, int n) {
memcpy(a, b, n * sizeof(int));
}
// foo(int*, int const*, int):
// movsx rdx, edx
// sal rdx, 2
// jmp memcpy尾调用优化。
优化前需要 call memcpy + ret。如果 jmp memcpy 就不会保存栈帧,这样的话 memcpy 里的 ret 就会直接返回到 foo 的调用方,效果是一样的。
3. 右值都存在寄存器,左值都存在内存,这个说法对吗
显然不对。左值右值的分类方法是,泛左值有值和地址,纯右值只有值没有地址。
寄存器和内存是实现的概念,跟 c++ 无关,大多数情况都是看编译器优化的。例如内存里的值如果被频繁读取,那可能被优化成只读一次,暂存到寄存器上,之后一直用寄存器了。
4. 字符串字面量是左值
这算是个特例,可以对它取地址。
#include <cstdio>
int main() {
const void* p = &"123";
std::printf("%p\n", p);
}