在c++中有一種運算符叫sizeof,這個運算其實可以依靠兩句宏定義來實作;
1 #include <stdio.h>
2
3 #define sizeof_T(T) ((size_t)((T*)0+1)) ///求類型的大小
4 #define sizeof_V(T) ((size_t)(&T+1)-(size_t)(&T)) ///求變量的大小
5
6 int main() {
7 int a=1, b[3]={0};
8 printf("這個類型大小:%d \n這個類型單個變量的大小:%d \n這個類型數組變量的大小%d\n", sizeof_T(int), sizeof_V(a), sizeof_V(b));
9 return 0;
10 }
那麼為什麼可以這樣實作呢?
對于求類型大小的sizeof_T:
首先我們通過(T*)0得到一個指向00000000的指針,而且這個指針是int類型的,現在我們将這個指針+1。比如我們用一個int *p指針指向一塊new int[10]的位址,那麼此時很顯然(p+1)-p==4而不是1,因為我們其實不是在位址上加1,而是讓指針向前前進了一步,而這一步就是T這個類型的大小,也就是我們求的其實是指針步長。
可以通過以下程式發現這個特點,然後我們将00000000位置的指針向前移動一步,很顯然,這個時候我們就得到了這個類型的大小。
1 #include <stdio.h>
2 #include <iostream>
3 using namespace std;
4 int main() {
5 char *p=new char[10];
6 int *q=new int[10];
7 printf("%p %p\n%p %p\n", p, p+1, q, q+1);
8 delete p;
9 delete q;
10 return 0;
11 }
對于求變量大小的sizeof_V:
也是利用了指針步長的原理,這裡值得注意的有兩點.
一是因為這裡我們不是類型,是以說不可能定義一個指向0的指針,隻能将自己的位址拿來運算。
二是數組名有一個特性,對于int p[10];這個數組,&p+1的值并不是數組首位址加上指針步長,此時的步長是數組本身,也就是一步跨越了整個數組。
第二點可以通過以下程式來驗證
1 #include <stdio.h>
2 int main() {
3 int p[3];
4 printf("%p %p\n", p, &p+1);
5 return 0;
6 }
是以由以上特性我們就可以手動實作sizeof的功能了,說白了就是求指針步長。