今天吃饭的路上和同学说起,他说发现了 c 语言中能够通过指针p指向一个int 数组array,然后把指针的值保存为 int 型 变量 address,再对 int 型的指针地址address+4,再把存着数组下一个地址的 int 变量转为 int 型指针, 这样还能够访问数组的下一个变量。
int array[5]={1,2,3,4,5};
int *p=array;
unsigned long address = (unsigned long)p;
address +=sizeof(int);
printf("%p:",p);
printf("%d\n",*p);
printf("%p:",(int*)address);
printf("%d\n",*(int*)address);
output:
0x7ffeefbff4a0:1
0x7ffeefbff4a4:2
Program ended with exit code: 0
然后我就想着,一般的情况下对指针+1,会自动指向下一个存有变量的地址,现在既然已经知道指针指向的地址了,如果我对指针的值+1,再把它转为指针看一下会发生什么?
int array[5]={1,2,3,4,5};
int *p=array;
unsigned long address = (unsigned long)p;
for(int i=0;i<5;++i){
printf("%p:",(int*)address); // 内存地址
printf("%x\n",*(int*)address++); // 值
}
output:
0x7ffeefbff4a0:1
0x7ffeefbff4a1:2000000
0x7ffeefbff4a2:20000
0x7ffeefbff4a3:200
0x7ffeefbff4a4:2
Program ended with exit code: 0
看到这个结果疑惑了好久,为什么 2 右变是六个 0,四个 0,后来讨论了才想起来,可能与 cpu 的存储方式有关,英特尔的 cpu 一般都是小端存储。小端存储是将高有效位存储在低地址中,而低有效位存储在高地址中。
假设变量 x 类型为 int,位于地址 0x100
处,它的十六进制值为 0x01234567
。根据不同机器的存储方式, 可以看下表。
… | 0x100 | 0x101 | 0x102 | 0x103 | 0x104 |
---|---|---|---|---|---|
大端法 | 01 | 23 | 45 | 67 | … |
小端法 | 67 | 45 | 23 | 01 | … |
由此可知,array 数组在我的电脑里面是这样存储的。
… | 0x7ffeefbff4a0 | 0x7ffeefbff4a1 | 0x7ffeefbff4a2 | 0x7ffeefbff4a03 |
---|---|---|---|---|
01 | 00 | 00 | 00 |
0x7ffeefbff4a4 | 0x7ffeefbff4a5 | 0x7ffeefbff4a6 | 0x7ffeefbff4a07 | … |
---|---|---|---|---|
02 | 00 | 00 | 00 |
当我把指针指向由0x7ffeefbff4a0
指向0x7ffeefbff4a1
,显而易见此时内存里面的内容为00 00 00 02
,因为我强行把这块内容当做 int 型读取出来,此时按照高有效位在低地址的小端存储模式,读出来就是 02 00 00 00
。
显而易见,
0x7ffeefbff4a2
的内容为00 00 02 00
,读取为 00 02 00 00
0x7ffeefbff4a3
的内容为00 00 02 00
,读取为 00 00 02 00
0x7ffeefbff4a4
的内容为02 00 00 00
,读取为 00 00 00 02
。
:如果觉得写的不错,请我喝杯饮料吧🥰