指针指向数组的地址
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int* ptr = (int*)(&a + 1);
printf("%d,%d", *(a + 1), *(ptr - 1));
return 0;
}
解析:
-
(int*)(&a + 1)-&a的类型为int(*)【5】,加1还是这个类型,因为用指针指向它,所以强制转换类型为int*,这样他就是指针了(指针指向数组的地址需要强制数组地址的类型转换为指针类型)
-
*(a+1)中,a不是特殊情况在这表示数组首元素的地址,加1为第二个元素的地址,在解引用找到第二个元素- -2
-
*(ptr - 1),ptr指向&a+1的地址,减1往前移动一个指针再解引用会找到元素5
指针类型决定指针的运算
结构体的大小是20个字节
unsigned long 的大小是1个字节
假设p 的值为0x100000。 如下表达式的值分别为多少?
struct Test
{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
}* p;
int main()
{
printf("%p\n", p + 0x1);
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);
return 0;
}
解析:
- p + 0x1,这里加1- -也就是加20个字节(结构体的大小为20个字节)--0x100014(这里的16进制的14- -为10进制就是20)
- p本来是指针类型,被强制转换为无符号长整型- -这里加1- -也就是加1(unsigned long 的字节为1)- -0x100001
- p本来是指针类型,被强制转换为无符号整型- -这里加1- -也就是加4(int 的字节为4)-0x100004
数组地址类型和指针
int main()
{
int a[4] = { 1, 2, 3, 4 };
int* ptr1 = (int*)(&a + 1);
int* ptr2 = (int*)((int)a + 1);
printf("%x,%x", ptr1[-1], *ptr2);
return 0;
}
-
(int*)(&a + 1)-&a为int(*)【4】类型,加1还是这个类型,所以强制转换为int*,这样他就是指针了
图解
-
%X的意思是以十六进制数形式输出整数
逗号表达式、指针
#include <stdio.h>
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int* p;
p = a[0];
printf("%d", p[0]);
return 0;
}
解析,
- 注意在二维数组中不是{ },而是(),说明是逗号表达式,二维数组可以写为inta[3][2]={1,3,5}
所以二维数组的存储情况在下图
二维数组,数组指针
int main()
{
int a[5][5];
int(*p)[4];
p = a;//int (*)[5]
printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
return 0;
}
图解
指针、数组
int main()
{
int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int* ptr1 = (int*)(&aa + 1);
int* ptr2 = (int*)(*(aa + 1));
printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
return 0;
}
解析
- (int*)(&aa + 1)-&a为int(*)【10】类型,加1还是这个类型,所以强制转换为int*,这样他就是指针了
- &aa表示二维数组的地址,加1跳过整个数组,如图,再用ptr1指向&aa+1,所以ptr1- -减1- -ptr1指针向前移动一个位置(在内存中- -移动了四个字节(因为它是int*类型),解引用就会找到10这个元素
- aa不是特殊情况,所以在二维数组中表示首元素地址(第一行的地址),加1- -跳过第一行指向第二行的地址,所以ptr2也指向这里,ptr2-1就指向如图位置,解引用就会找到第5这个元素
指针数组
#include <stdio.h>
int main()
{
char* a[] = { "work","at","alibaba" };
char* * pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}
- char*a[] - -每个元素都是char *
有点难下面的,理解完就会心情大好,加油!!
三级指针、二级指针、一级指针- - -难点
int main()
{
char* c[] = { "ENTER", "NEW", "POINT", "FIRST" };
char** cp[] = { c + 3, c + 2, c + 1, c };
char*** cpp = cp;
printf("%s\n", **++cpp);
printf("%s\n", *-- * ++cpp + 3);
printf("%s\n", *cpp[-2] + 3);
printf("%s\n", cpp[-1][-1] + 1);
return 0;
}
- char*的内容就是指c这个字符串的数组名,字符串的数组名是指向字符串的首地址
- 打印的时候先看指向哪个字符的地址,这个字符后面的所有字符都输出
-
* * ++cpp的增加解释:第一个char*的地址解引用后,得到c这个字符串的首地址p,后面的字符oint也跟着输出,所以拿到的是point