4个二进制位可以表示一个16进制数字
1111 -->f
指针类型的意义:
指针类型决定了:指针解引用的权限有多大(整型指针解引用访问4个字节,字符型指针解引用只能访问1个字节)
指针类型决定了,指针走一步,能走多远(步长)
例题1:
1 2 3 4 5 6 int a = 0x11223344 ; char * pc = &a;*pc = 0 ; int * pa = &a;*pa = 0 ;
char* 的指针解引用就只能访问一个字节,而 int* 的指针的解引用能访问四个字节。
例题2:
1 2 3 4 5 6 7 int arr[10 ] = { 0 };int * p = arr;char * pc = arr;printf ("%p\n" , p);printf ("%p\n" , p + 1 );printf ("%p\n" , pc);printf ("%p\n" , pc + 1 );
野指针:指针指向的位置是不可知的
为什么出现野指针:
指针使用时未初始化:
指针越界:
1 2 3 4 5 6 7 8 9 10 int arr[10 ] = { 0 };int * p = arr;int i = 0 ;for (i = 0 ; i <= 10 ; i++){ *p = i; p++; }
指针指向的空间释放:
1 2 3 4 5 6 7 8 9 10 11 12 13 int * test () { int a = 10 ; return &a; } int main () { int *p = test(); *p = 20 ; return 0 ; }
退出test函数后空间释放,找不到指针p的地址。
总结:如何规避野指针?
1.指针初始化
2.小心指针越界
3.指针指向空间释放即设置NULL
4.指针使用之前检查有效性
指针的运算:
指针±整数:
1 2 3 4 5 6 7 8 int arr[10 ] = { 1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 };int * p = arr; int * pend = arr + 9 ; while (p < pend){ printf ("%d\n" , *p); p++; }
指针-指针:
1 2 3 4 5 6 7 8 9 int main () { int arr[10 ] = { 1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 }; char c[5 ]; printf ("%d\n" , &arr[9 ] - &c[0 ]); printf ("%d\n" , &arr[9 ] - &arr[0 ]); return 0 ; }
两指针相减的前提是指针指向同一块空间,指针-指针得到的是两个指针之间元素的个数
例题:求字符串长度:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 int my_strlen (char * str) { char * start = str; while (*str != '\0' ) { str++; } return str - start; } int main () { int len = my_strlen("abc" ); printf ("%d\n" , len); return 0 ; }
指针和数组:
1 2 3 4 5 6 7 8 9 int main () { int arr[10 ] = { 0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 }; int * p = arr; int i = 0 ; for (i = 0 ; i < 10 ; i++) { printf ("&arr[%d]=%p <==> *(p+%d)=%p\n" ,i,&arr[i],i,p+i); }
arr[i]=*(p+i) =*(arr+i);
&arr[i]=p+i=arr+i;
1 arr[2 ] <==> *(arr+2 ) <==> *(p+2 ) <==> *(2 +p) <==> *(2 +arr) == 2 [arr]
二级指针:
1 2 3 4 5 6 7 8 int main () { int a = 3 ; int * pa = &a; int ** ppa = &pa; printf ("%d,%d,%d\n" , a,*pa,**ppa); }
禁止套娃!!!