mikewzp

 

“搅和”在一起

指针用来指向具体某一份数据,数组名用来指代一组数据;它们的名字用来指定不同的内存块。

数组和指针的关系颇像诗和词的关系,它们都是一种文学形式,有不少共同之处,但在实际的表现手法上又各有特色。

从哲学的高度来看,数组名既有一般性也有特殊性:一般性表现在数组名也用来指代特定的内存集合,也有类型和长度;特殊性表现在数组名有时候会转换为一个指针,而不是它所指代的数据本身的值。

堆对齐:

#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。

posted on 2023-06-10 15:53  武装部  阅读(17)  评论(0)    收藏  举报

导航