我们将请出我们今天重要的嘉宾来为我们的指针的讲解出一份力:
**sizeof()**函数:
sizeof函数是一个用于计算数组大小的函数,它能够计算一个函数有多少字节。
我们今天就利用sizeof函数来帮助我们进行解析指针。
接下来直接上题:
第一题:
struct Test
{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
} * p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
//0x开头的数字是16进制的数字
int main()
{
p = (struct Test*)0x100000;
printf("%p\n", p + 0x1);
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);
return 0;
}
题解:
在vs上和x86环境下,我们的地址大小为4。
对于第一个:我们可以简单看出,是将 一个结构体指针——p + 0x1,其中加上0x1,我们可以直接看作+1;那么对一个指针直接加一,是什么结果呢?
答:再整个同类型的指针,对此题,也就是在加上一个struct Test类型的大小,也就是,加上20字节 ,因此答案就是:00100014,前面的00是为了补足32位。
对于第二个:我们可以简单看出,强制将p转换为了无符号长整型,而对无符号整型加一,就是在其值上加1,所以答案就是:00100001。
对于第三个:我们可以简单看出,强制将p转换为了无符号整型指针,而对无符号整型指针加一,就是在其值上加4,所以答案就是:00100004。
第二题:
int main()
{
int aa[2][5] = { 10,9,8,7,6,5,4,3,2,1 };
int* ptr1 = (int*)(&aa + 1);//第二行1后面的地址,&aa+1相当于跳过了整个数组
int* ptr2 = (int*)(*(aa + 1));//第二行起始地址,即5
printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));//ptr1-1,即从1后面的地址变为1,ptr2-1,即从5减到上一行的6
return 0;
}
题解:
对于二维数组来说,我们可以将它划分为两个部分,列如上面的数组:
int aa[2][5] = { 10,9,8,7,6,5,4,3,2,1 };---->aa[0][]={10,9,8,7,6}和aa[1][]={5,4,3,2,1}
这只是我们抽象出来的,在内存中储存依旧是连续的。
对于ptr1来说:&aa是整个数组的地址,加一就跳过了整个数组,因为本身地址就是int *类型,因此强制转换为int *没有影响。
对于ptr2来说:aa是第一行的地址,第一行的地址加一,就是第二行起始位置。
然后在printf中:ptr1-1,就指向了数组最后一个,结果为1,prt2-1,就到了第一行的最后一个,结果就是:5。
第三题:
#include <stdio.h>
int main()
{
char* a[] = { "work","at","alibaba" };//work\0 at\0 alibaba\0
char** pa = a;//pa的类型是char**,是一个二级指针
pa++;
printf("%s\n", *pa);
return 0;
}
题解:
有第一行和第二行我们可以得知:a是一个字符串数组,pa是一个二级指针。
对于一个二级指针++一次,就是跳过一个char *类型的大小,故pa
由指向a的第一个字符串,指向了第二个字符串地址,所以,解引用pa就是第二行元素,答案就是:at
第四题:
int main()
{
int a[4] = { 1, 2, 3, 4 };
int* ptr1 = (int*)(&a + 1);//跳过整个数组,在4后面
int* ptr2 = (int*)((int)a + 1);
printf("%x,%x", ptr1[-1], *ptr2);//ptr1[-1]相当于*(ptr1-1),为4
return 0;
}
题解:
对于ptr1来说:&a就是取整个数组的地址,ptr1+1就到了指向了4后面。而ptr1[-1]就是访问ptr1当前位置的后一个数据类型,也就是:4
对于ptr2来说:将a(这里a是数组第一个的地址)强制转化为int类型,也就是01000000,+1后就是01000001(int型),然后在转换为整型指针,也就是:01000001(int*型),也就是移动了一个字节;而对地址来说,有四个字节,因此ptr2此时指向的内存地址不再是10(下面表格内容),而是跳过了01,指向01后面的00,而在对ptr2解引用,需要四个字节的地址,就读取到00 00 00 02,然后高地址放在高位,低地址放在地位,就是:02 00 00 00 因此打印出来就是:2000000。
扩充:由于我所使用的是小端机器,和32位环境下:
对于数组的内存储存可以得知:
01000000 (1) | 02000000(2) | 03000000 (3) | 04000000(4) |
---|