C语言简易sizeof宏实现原理与char*类型转换作用解析
原问题背景
我在学习C语言时遇到了一个简化版sizeof实现,代码如下:
#include <stdio.h> #define mySizeof(type) ((char*)(&type + 1) - (char*)(&type)) int main() { char x; int y; double z; printf("mySizeof(char) is : %ld\n", mySizeof(x)); printf("mySizeof(int) is : %ld\n", mySizeof(y)); printf("mySizeof(double) is : %ld\n", mySizeof(z)); }
注:本次不讨论该实现的兼容性问题,仅解释其工作逻辑,该实现对示例中三类基础变量可以正常运行。
核心疑问:
- 上述
mySizeof宏的运行原理是什么? - 宏中
char*强制类型转换的作用是什么? - 为什么两个实际地址差4字节的
int*指针直接相减结果为1,和实际字节数不一致?
对应的验证测试代码:
#include <stdio.h> #define Address(x) (&x) #define NextAddress(x) (&x + 1) int main() { int n = 1; printf("address is : %lld\n", Address(n)); printf("next address is : %lld\n", NextAddress(n)); printf("size is %lld\n", NextAddress(n) - Address(n)); return 0; }
测试输出:
address is : 140721498241924 next address is : 140721498241928 size is 1
原理解释
1. C语言指针运算的核心规则
C语言中指针的加减运算不是以字节为单位,而是以指针指向的类型的大小为单位。
举个例子:
- 对于
int* p,p+1不是地址值加1,而是地址值加sizeof(int),也就是指向内存中下一个相邻的int类型变量的位置。 - 两个同类型指针相减,得到的结果也不是地址的字节差值,而是两个指针之间间隔的对应类型元素的个数。
这就是测试中看到的现象:两个int*指针实际地址差4字节(刚好是一个int的长度),直接相减得到的结果是1——因为这两个指针之间刚好隔了1个int类型的元素。
2. mySizeof宏的工作逻辑
宏的完整逻辑分三步:
- 第一步:
&type拿到变量的首地址,这个指针的类型是指向变量对应类型的指针,比如传入int变量y时,&y是int*类型。 - 第二步:
&type +1按照指针运算规则,会向后偏移一个对应类型变量的长度,刚好指向当前变量内存后面紧邻的位置。 - 第三步:把前后两个地址都强转成
char*类型再相减,得到最终的字节长度结果。
3. char*强转的作用
C标准明确规定sizeof(char)的结果恒为1,也就是说char*类型的指针运算单位是1字节。
当我们把两个地址都转成char*之后,指针相减得到的结果就是两个地址之间间隔的char类型元素个数,也就是间隔的字节数,刚好等于原类型的大小。
如果不加这个强转,就会出现测试代码里的情况:两个同类型指针相减永远得到1,根本算不出实际字节长度。
内容的提问来源于stack exchange,提问作者Chris Bao
相关产品推荐
相关产品推荐

