指针
重点
1.指针是什么
2.指针和指针类型
3.野指针
4.指针运算
5.指针和数组
6.二级指针
7.指针数组
1.指针是什么
指针就是地址,地址就是指针,意思是通过它能够找到以它为地址的内存单元
一个小的内存单元的大小是一个字节
对应32根地址线,有232个地址(232byte = 4G)
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000001
…
11111111 11111111 11111111 11111111
指针的大小都是4个字节
#include<stdio.h>
#include<string.h>
int main() {
printf("%d", sizeof(int*));
printf("%d", sizeof(char*));
printf("%d", sizeof(double*));
printf("%d", sizeof(float*));
}
那么指针类型又有什么意义呢?
指针类型决定了指针在解引用操作时,能够访问空间的大小
int *p 可以访问4个字节
char* p 可以访问1个字节
double *p 可以访问8个字节
野指针
1.野指针未初始化
#include<stdio.h>
int main() {
int* p;
*p = 20;
return 0;
}
2.指针越界访问
3.指针指向的空间已经被释放
如何避免野指针? 在使用前先判断if( p!=NULL),这里的p是地址
指针运算
指针±整数
#include<stdio.h>
int main() {
int arr[] = { 1,2,3,4,5,6,7,8,9,10};
int len = sizeof(arr) / sizeof(arr[0]);
int i;
int* p =&arr[9];
for (i = 0; i < len; i++) {
printf("%d\n", *p);
p--;
}
}
体现的是地址的加加
#include<stdio.h>
int main() {
int arr[] = { 1,2,3,4,5,6,7,8,9 };
printf("%d\n", (&arr[9] - &arr[0]));
printf("%d\n", (&arr[0] - &arr9));
}
指针的相减一定指向的是同一块区域!也就是说,在同一个数组中才可以相加减,并且结果是中间相差的元素数(大减小,小减大是负数)
#include<stdio.h>
int my_strlen(char* arr) {
char* start = arr;
char* end = arr;
while (*end != '\0') {
end++;
}
return end - start;
}
int main() {
char arr[] = "asdf";
int len;
len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
第三种求strlen的方法,用的是指针加的运算,还有递归和循环的方法
注意点
arr不表示首地址的两种特殊的情况
#include<stdio.h>
int main() {
int arr[10] = { 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);
}
二级指针
#include<stdio.h>
int main() {
int i = 10;
int* pi = &i;
int** ppi = π
**ppi = 5;
printf("i=%d,*pi=%d ,**ppi =%d", i, *pi, **ppi);
}
指针数组
好孩子->好的孩子
指针数组->指针表示的数组
#include<stdio.h>
int main() {
int a = 1;
int b = 2;
int c = 3;
int* pA = &a;
int* pB = &b;
int* pC = &c;
int* pArr[] = { &a,&b,&c };
int i;
for (i = 0; i < 3; i++) {
printf("%d\n",*(pArr[i]));
printf("%d\n", *(*(pArr + i)));
printf("%d\n", **(pArr + i));
}
}
|