“搅和”在一起
指针用来指向具体某一份数据,数组名用来指代一组数据;它们的名字用来指定不同的内存块。
数组和指针的关系颇像诗和词的关系,它们都是一种文学形式,有不少共同之处,但在实际的表现手法上又各有特色。
从哲学的高度来看,数组名既有一般性也有特殊性:一般性表现在数组名也用来指代特定的内存集合,也有类型和长度;特殊性表现在数组名有时候会转换为一个指针,而不是它所指代的数据本身的值。
堆对齐:
#include <stdio.h> #include <stdlib.h> int m; char c; int n; int main(){ printf("&m: %p\n&c: %p\n&n: %p\n", &m, &c, &n); // system("pause"); return 0; }
&m: 0x55891858f014 &c: 0x55891858f018 &n: 0x55891858f01c
栈对齐:
#include <stdio.h> int main(){ int a[6] = {0, 1, 2, 3, 4, 5}; int *p = a; char b = 100; int len_a = sizeof(a) / sizeof(int); int len_p = sizeof(p) / sizeof(int); for(int i=0;i<6;++i) { printf("%d, %p\n",a[i],&a[i]); } char c = 101; printf("p=%p, &p=%p, a=%p, &a=%p\n",p,&p,a,&a); printf("%ld\n", sizeof(p)); printf("&len_a=%p\n", &len_a); printf("len_a = %d\n", len_a); printf("&len_p=%p\n", &len_p); printf("len_p = %d\n", len_p); printf("size(len_a) = %ld\n", sizeof(len_a)); printf("%c, &char_b=%p\n", b, &b); printf("%c, &char_c=%p\n", c, &c); return 0; }
0, 0x7ffd01addf60 1, 0x7ffd01addf64 2, 0x7ffd01addf68 3, 0x7ffd01addf6c 4, 0x7ffd01addf70 5, 0x7ffd01addf74 p=0x7ffd01addf60, &p=0x7ffd01addf58, a=0x7ffd01addf60, &a=0x7ffd01addf60 8 &len_a=0x7ffd01addf4c len_a = 6 &len_p=0x7ffd01addf50 len_p = 2 size(len_a) = 4 d, &char_b=0x7ffd01addf4a e, &char_c=0x7ffd01addf4b
对于64位Linux很明显是从0x7ff栈的起始端由大到小分配:
1)先是把6个整型数组分配;指针p占据8个字节,从58拱到60
2)局部变量先分配两个整型,然后才分配两个字符型:没有严格按照声明的顺序来,估计是编译器内部的优化问题
3)len_p与len_a之间,从50到4c隔着一个整型的距离(4个字节);接着len_a的地址4c, 给出了两个char型的地址:4b, 4a。
唯一让人困惑的就是,len_p为何会与指针p留两倍整型的间隔(58~50); p指针在64位系统占8个字节没毛病,但它是从58开始往高走到60这段内存。
所以就只能是归咎到整型与指针之间做了个八字节对齐,所以娶到了50。
浙公网安备 33010602011771号