内存分配时sizeof *ptr与sizeof **ptr的差异及问题咨询
sizeof **ptr 和 sizeof *ptr 的区别,以及char*场景下段错误的原因 两者的核心差异
sizeof **ptr:计算的是指针最终指向的底层数据类型的大小。比如你提供的代码里,ptr是double**类型,**ptr对应double类型,结果就是sizeof(double)(通常为8字节)。sizeof *ptr:计算的是一级指针本身的大小。这里*ptr是double*类型,结果就是指针的内存占用——64位系统下是8字节,32位系统下是4字节。
你处理int*、double*时觉得两者无差异,只是巧合:你的系统上这些底层数据类型的大小刚好和指针大小一致(比如64位下double和double*都是8字节)。换去32位系统,指针大小是4字节,double仍为8字节,两者结果就会不同。
为什么char*场景下会出现段错误?
先明确一个关键事实:sizeof是编译期运算符,它只会根据表达式的静态类型计算大小,不会实际执行指针解引用操作。所以sizeof **ptr本身不可能触发段错误。
你遇到的问题,大概率是调用函数时传参错误:比如传入了NULL或未初始化的char**,导致执行(*ptr) = malloc(...)时,解引用了非法地址。举个例子:
char *p; // 错误示范:传入NULL,*ptr就是解引用空指针,直接触发段错误 func(10, NULL); // 正确做法:传入&p,让ptr指向p这个有效指针变量 func(10, &p);
还有一种极端罕见的情况:如果代码使用了C99的变长数组(VLA),且**ptr属于VLA类型,这时候sizeof需要运行时计算,才可能因解引用无效指针出问题,但这种场景极少出现。
推荐写法
为了避免踩坑,推荐两种更安全的写法:
- 直接写目标类型的
sizeof:比如分配double数组就写sizeof(double),清晰直白。 - 保留
sizeof(**ptr):它和指针类型绑定,后续如果把double**改成int**,无需手动修改sizeof里的类型,更省心。
但无论用哪种写法,调用函数时一定要确保传入的ptr是指向有效指针变量的地址,别传NULL或野指针。
内容的提问来源于stack exchange,提问作者Luguecos
相关产品推荐
相关产品推荐

