当你不知道指针变量初始化什么时,可以初始化为空指针
int *p=NULL;
我们看NULL的定义,可以看出NULL是0被强制转化为Void* 类型的0;实质还是个0;
指针运算
- 指针+- 整数
- 指针-指针
- 指针的关系运算
指针+- 整数
下面这段代码实现的是打印数组的元素。
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int i = 0;int sz = sizeof(arr) / sizeof(arr[0]);int* p = arr;for (i = 0; i < sz; i++){printf("%d ", *p);p = p + 1;}return 0;
}
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };printf("%d\n", & arr[9] - &arr[0]);return 0;
}
指针-指针得到的是中间元素的个数
例如:求字符串的长度。模拟实现strlen这个函数
int my_strlen(char* str)
{char* start = str;char* end = str;while (*end != '\0'){end++;}return end - start;
}
int main()
{char arr[] = "bit";int len = my_strlen(arr);printf("%d\n", len);return 0;
}
指针与数组
数组名是首元素地址,怎么证明呢?通过下面的代码进行证明
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };printf("%p\n", arr);printf("%p\n", &arr[0]);return 0;
}
注意:两个例外
1.&arr - &数组名 - 数组名不是首元素地址-数组名表示整个数组 ,所以&数组名取出的是整个数组的地址,
2.sizeof(arr) - sizeof(数组名)-数组名表示整个数组,sizeof(数组名)计算的是整个数组的大小。单位字节
下面的代码我们来看看他们的区别
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };printf("%p\n", arr);printf("%p\n", arr+1);printf("%p\n", &arr[0]);printf("%p\n", &arr[0]+1);printf("%p\n", &arr);printf("%p\n", &arr + 1);return 0;
}
调试代码如下:
前面两个都是地址加4,最后一个加了40,(16进制的运算)
可以看出&arr是整个数组的地址,整个数组的地址加1,是跳过(整型)4*10(元素个数)=40
既然可以把数组名当成地址存放到一个指针中,我们使用指针来访问其中任意一个就成为可能。
看下面的代码:
int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9,0 };int* p = arr; //指针存放数组首元素的地址int sz = sizeof(arr) / sizeof(arr[0]);int i = 0;for (i = 0; i < sz; i++){printf("&arr[%d] = %p <====> p+%d = %p\n", i, &arr[i], i, p + i);}return 0;
}
可以看出是是一一对应的关系,所以 p+i 其实计算的是数组 arr 下标为i的地址。 那我们就可以直接通过指针来访问数组。
打印数组元素
int main()
{int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };int* p = arr; //指针存放数组首元素的地址int sz = sizeof(arr) / sizeof(arr[0]);int i = 0;for (i = 0; i < sz; i++){printf("%d ", *(p + i));}for (i = 0; i < sz; i++){printf("%d \n", arr[i]);}return 0;
}
二级指针
指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?
所以我们就有二级指针
a 的类型是int
pa 的类型是int*
ppa 的类型是int** 最后一个*表示是指针,指向的对象是int*
int main()
{int a = 10;int* pa = &a;int** ppa = &pa;printf("%d\n", **ppa);
}
指针数组
与数组指针的区别 就像好孩子,重点是孩子,
指针数组-数组 --存放指针的数组。
数组指针-指针。
为啥要与指针数组,跟数组的由来一样,看下面的代码,对同一类型的地址存储,如果一个一个写下去,太麻烦了,所以我们要有指针数组来存放,这样就方便多了。
int main()
{int a = 10;int b = 20;int c = 30;int* pa = &a;int* pb = &b;int* pc = &c;return 0;
}
怎么初始化呢?
int arr[10];
int* arr1[3];//指针数组初始化
存放的类型都是int* 的类型
int* arr1[3] = { &a,&b,&c };
int main()
{int a = 10;int b = 20;int c = 30;int* arr2[3] = { &a,&b,&c };int i = 0;for (i = 0; i < 3; i++){printf("%d \n", *(arr2[i]));}return 0;
}