关于memcpy一个字符串到紧邻结构体内存空间处的疑问

NoSay
  • 440
#include <stdlib.h>
#include <string.h>
int main() {

    struct string{
        int len;
    };

    typedef struct string str;

    char *s = "hello";
    str *p = (str*)(malloc(sizeof(str) + strlen(s) + 1));//分配足够存下一个字符串的结构体
    p->len = strlen(s);
    memcpy(p + 1, s, strlen(s));//将字符串拷贝到紧邻结构体的内存处

}

  • 这段程序的目标:将字符串拷贝到紧邻结构体的内存空间处,与结构体原有字段构成连续的内存空间(类似柔性数组的作用)。首先我们给它分配了sizeof(str) = 4 + strlen(s) = 2 + 1 = 7个字节,由于内存对齐的原因,需要补1个字节,所以声明的p结构体共占用8个字节,可以满足复制的需求。如图:

  • 预期结果:如结构体的地址为0x602010,那么he字符串的位置应该在0x602010 + 0x4 = 0x602014位置上,占用2字节内存空间。
  • 实际结果:该字符串却存到了0x602020位置上,与结构体起始地址0x602010相差了16个字节。通过gdb看到len字段的地址也是0x602010,sizeof(p->len)的值为4,说明len字段占用了0x602010 ~ 0x602014的地址,但是接下来这段0x602014 ~ 0x602020地址是没有任何值存储的(如下图),想问一下为什么会出现这种情况,谢谢。,
  • 首先是一个很奇怪的现象,0x602010 + 0x4,打印出来的结果居然是:0x602020,为什么不是0x602014,而是0x602020呢?

  • 先后打印结构体的值、字符串的值与地址、结构体len字段的地址、结构体的地址(与len字段地址相同),发现并不符合预期:

  • 查看0x602014 ~ 0x602020处地址的值:

  • 根据该值画出预期内存情况与实际内存情况:

回复
阅读 1.8k
1 个回答
✓ 已被采纳

当p的类型为 str* 的时候,p + 4 的值是 p + 4*sizeof(str)

例:试试在gdb里p这几个值

(str*)(p) + 1
(void*)(p) + 1
(int)(p) + 1

剩下的你应该能自己推出来了

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏