魔鸡马奇克2免安装绿色中文版
175M · 2025-09-17
sizeof(uintptr_t)
个字节对齐的。sizeof(uintptr_t)
个字节对齐)。并解释如果不满足这个条件,你能想到的最简单的做法是回退到逐字节拷贝。#include <iostream>
#include <cassert>
void* MemoryMove(void* dst, const void* src, size_t n) {
if (!dst || !src) {
assert(dst);
assert(src);
return nullptr;
}
// 正向拷贝
if (dst <= src) {
size_t head_bytes = (sizeof(uintptr_t) - (reinterpret_cast<uintptr_t>(dst) % sizeof(uintptr_t))) % sizeof(uintptr_t);
n -= head_bytes;
auto* slow_dst_ptr = reinterpret_cast<uint8_t*>(dst);
auto* slow_src_ptr = reinterpret_cast<const uint8_t*>(src);
while (head_bytes--) {
*slow_dst_ptr = *slow_src_ptr;
++slow_dst_ptr, ++slow_src_ptr;
}
size_t fast_steps = n / sizeof(uintptr_t);
if (reinterpret_cast<uintptr_t>(slow_src_ptr) % sizeof(uintptr_t) == 0 && fast_steps > 0) {
n %= sizeof(uintptr_t);
auto* fast_dst_ptr = reinterpret_cast<uintptr_t*>(slow_dst_ptr);
auto* fast_src_ptr = reinterpret_cast<const uintptr_t*>(slow_src_ptr);
assert((uintptr_t)fast_dst_ptr % sizeof(uintptr_t) == 0);
assert((uintptr_t)fast_src_ptr % sizeof(uintptr_t) == 0);
while (fast_steps--) {
*fast_dst_ptr = *fast_src_ptr;
++fast_dst_ptr, ++fast_src_ptr;
}
slow_dst_ptr = reinterpret_cast<uint8_t*>(fast_dst_ptr);
slow_src_ptr = reinterpret_cast<const uint8_t*>(fast_src_ptr);
}
while (n--) {
*slow_dst_ptr = *slow_src_ptr;
++slow_dst_ptr, ++slow_src_ptr;
}
}
// 反向拷贝
else {
size_t tail_bytes = (reinterpret_cast<uintptr_t>(dst) + n) % sizeof(uintptr_t);
auto* slow_dst_ptr = reinterpret_cast<uint8_t*>(dst) + n - 1;
auto* slow_src_ptr = reinterpret_cast<const uint8_t*>(src) + n - 1;
n -= tail_bytes;
while (tail_bytes--) {
*slow_dst_ptr = *slow_src_ptr;
--slow_dst_ptr, --slow_src_ptr;
}
size_t fast_steps = n / sizeof(uintptr_t);
if ((reinterpret_cast<uintptr_t>(slow_src_ptr) + 1) % sizeof(uintptr_t) == 0 && fast_steps > 0) {
n %= sizeof(uintptr_t);
auto* fast_dst_ptr = reinterpret_cast<uintptr_t*>(slow_dst_ptr - 7);
auto* fast_src_ptr = reinterpret_cast<const uintptr_t*>(slow_src_ptr - 7);
assert((uintptr_t)fast_dst_ptr % sizeof(uintptr_t) == 0);
assert((uintptr_t)fast_src_ptr % sizeof(uintptr_t) == 0);
while (fast_steps--) {
*fast_dst_ptr = *fast_src_ptr;
--fast_dst_ptr, --fast_src_ptr;
}
slow_dst_ptr = reinterpret_cast<uint8_t*>(fast_dst_ptr) + 7;
slow_src_ptr = reinterpret_cast<const uint8_t*>(fast_src_ptr) + 7;
}
while (n--) {
*slow_dst_ptr = *slow_src_ptr;
--slow_dst_ptr, --slow_src_ptr;
}
}
return dst;
}
void TestAnswer() {
char buffer1[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char buffer2[30] = { 0 };
memmove(buffer2, buffer1, 15);
std::cout << buffer2 << std::endl;
memmove(buffer1 + 2, buffer1, 15);
std::cout << buffer1 << std::endl;
char buffer3[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
memmove(buffer3 + 5, buffer3 + 2, 15);
std::cout << buffer3 << std::endl;
char buffer4[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
memmove(buffer4 + 2, buffer4 + 5, 15);
std::cout << buffer4 << std::endl;
}
void TestMyFunc() {
char buffer1[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char buffer2[30] = {0};
MemoryMove(buffer2, buffer1, 15);
std::cout << buffer2 << std::endl;
MemoryMove(buffer1 + 2, buffer1, 15);
std::cout << buffer1 << std::endl;
char buffer3[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
MemoryMove(buffer3 + 5, buffer3 + 2, 15);
std::cout << buffer3 << std::endl;
char buffer4[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
MemoryMove(buffer4 + 2, buffer4 + 5, 15);
std::cout << buffer4 << std::endl;
}
int main() {
TestAnswer();
std::cout << "---------------------" << std::endl;
TestMyFunc();
}
考察点:对内存对齐(Alignment)的理解。
面试官心理:“他想到了用 uintptr_t*,很好。但他知不知道这里面有个巨大的陷阱?他会不会直接 reinterpret_cast 然后就以为万事大吉了?这能区分出他是死记硬背还是真正理解了内存对齐的概念。”
预期表现:候选人在给出逐字节拷贝版本的代码实现后,能主动说出:“我这里的实现有一个简化,它假设了源和目的地址都是8字节对齐的。在实际情况中,如果地址不对齐,直接这样转换并访问,在某些CPU架构上会直接导致程序崩溃,在另一些架构(如x86)上也会因为CPU的额外处理而导致性能严重下降,违背了优化的初衷。”
考察点:是否了解现代计算机体系结构中真正的高性能方案。
面试官心理:“非常好,他连对齐的坑都知道了。那他知不知道在现实中,C/C++底层的标准库是怎么做到极致性能的?”
预期表现:在讨论完对齐问题后,候选人能进一步补充:“其实,要做到真正的极致性能,手写C++循环已经不是最佳方案了。现代编译器在开启优化后,很多时候能比手写的循环做得更好。而标准库(如Glibc)中的 memmove 实现,通常会利用CPU的SIMD(单指令多数据流)指令集,比如x86平台上的 SSE 或 AVX 指令,它们可以一次性操作128位(16字节)、256位(32字节)甚至512位的数据。这些实现是高度优化的、平台相关的,并且通常是用汇编或者编译器内置函数(Intrinsics)来编写的,这才是工业界的标准实现。”
175M · 2025-09-17
302M · 2025-09-17
318M · 2025-09-17