为何memcpy传入数组buff和&buff的执行效果完全相同?
为什么
memcpy(buff, msg, sizeof(msg))和memcpy(&buff, msg, sizeof(msg))执行效果一致? 问题背景
给定以下代码:
char buff[100] = {0}; char msg[] = "hello!"; memcpy(buff, msg, sizeof(msg)); // 或者 memcpy(&buff, msg, sizeof(msg));
这两行memcpy的执行效果完全一致,但按照常规理解,&buff似乎应该是取数组的地址,会把数据复制到存储数组地址的指针位置,而非数组本身的内存。比如用户设想的内存布局:
address | value | (name) -------------- --------- ---------------- 0x1000 | 'h' | (buff[0]) 0x1001 | 'e' | (buff[1]) ... etc __________________________________________ 0x5000-0x5008 | 0x1000 | (buf - char *) __________________________________________ 0x8000-0x8008 | 0x5000 | (&buf - char**) __________________________________________
用户无法理解为什么msg没有被写入0x5000地址覆盖0x1000。
核心原因:数组名的特殊性
你混淆了数组名和指针变量的本质区别:
buff是数组名,它不是一个存储数组地址的指针变量,而是直接代表整个数组的内存块。在大多数表达式中(比如作为函数参数时),数组名会隐式转换为指向数组第一个元素的指针(即&buff[0]),但它本身不是指针变量,没有单独的内存存储它的地址。&buff是取整个数组的地址,它的类型是char (*)[100](指向100个char的数组的指针),但这个地址的数值和数组第一个元素的地址&buff[0]完全相同——因为整个数组的起始位置就是第一个元素的位置。
为什么memcpy行为一致?
memcpy的第一个参数类型是void*,不管传入的是buff(转换为char*,指向buff[0])还是&buff(转换为void*,指向整个数组的起始地址),它们的地址数值完全相同。所以memcpy都会从这个相同的起始地址开始复制sizeof(msg)字节的数据,最终效果自然一致。
纠正你的内存布局误解
你设想的0x5000位置的指针变量根本不存在——buff是数组,它直接占用从0x1000开始的100字节内存,没有额外的内存存储“数组的地址”。只有当你显式定义一个指针变量时,比如:
char* p = buff;
这时候p才是一个指针变量,它会占用一块内存(比如0x5000)来存储buff的起始地址0x1000,此时&p才是这个指针变量的地址。
内容的提问来源于stack exchange,提问作者RemyBean
相关产品推荐
相关产品推荐

