第六章-指针
一、指针是什么
指针是内存中一个最小单元的编号,也就是地址
平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量
指针就是地址,口语中说的指针通常指的是指针变量
指针变量,用来存放地址的变量。
指针是用来存放地址的,地址是唯一标示一块地址空间的。
指针的大小在32位平台是4个字节,在64位平台是8个字节。
#include <stdio.h> int main() { int a = 10;//在内存中开辟一块空间 int *p = &a;//这里我们对变量a,取出它的地址,可以使用&操作符。 //a变量占用4个字节的空间,这里是将a的4个字节的第一个字节的地址存放在p变量 中,p就是一个之指针变量。 return 0; }
二、 指针和指针类型
针的类型决定了指针走多远
指针的类型决定了能操作几个字节。
#include<stdio.h> int main() { //printf("%d\n", sizeof(char*));//4 //printf("%d\n", sizeof(short*));//4 //printf("%d\n", sizeof(int*));//4 //printf("%d\n", sizeof(double*));//4 int a = 0x11223344; int* pa = &a; char* pc = &a; printf("%p\n", pa);//0096F718 printf("%p\n", pc);//0096F718 return 0; }
#include <stdio.h> int main() { int a = 0x11223344; int* pa = &a; char* pc =&a; printf("%p\n", pa); printf("%p\n", pa+1);//+4 printf("%p\n", pc); printf("%p\n", pc + 1);//+1 //指针的类型决定了指针走多远 //int* p;p+1-->4 //char* p;p+1-->1 //double* p; p + 1-- > 8; return 0; }
#include<stdio.h> int main() { int arr[10] = { 0 }; int* p = arr;//数组名-首元素地址 //char* p=arr;只能改10个字节 int i = 0; for (i = 0; i < 10; i++) { *(p + i) = 1;//把数组全改成1 } printf("%p\n", p); return 0; }
三、野指针
1.原因
(1) 指针未初始化
#include <stdio.h> int main() { //未初始化的指针变量 int* p;//局部变量指针未初始化,默认为随机值 *p = 20; return 0; }
(2) 指针越界访问
#include <stdio.h> int main() { //数组越界 int a[10] = { 0 }; int i = 0; int* p = a; for (i = 0; i <= 12; i++) { //当指针指向的范围超出数组arr的范围时,p就是野指针 *p = i; p++; //*p++=i; } return 0; }
(3)指针指向的空间释放
#include<stdio.h> int* test() { int a = 10;//局部变量,仅局部使用 return &a; } int main() { int* p=test(); printf("%d\n",*p);//再次访问非法 return 0; }
2.规避野指针
(1)指针初始化或赋值(NULL)
(2) 小心指针越界
(3) 指针指向空间释放即使置NULL
(4) 避免返回局部变量的地址
(5) 指针使用之前检查有效性(指针不为空)
四、 指针运算
1.指针+- 整数
#include<stdio.h> 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; //p++; } return 0; }
2.指针-指针
两个指针需要位于同一个空间
#include<stdio.h> int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; printf("%d\n", &arr[9] - &arr[0]); //9,求的是中间元素个数 return 0; }
#include<stdio.h> 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; }
3.指针的关系运算
五、 指针和数组
#include <stdio.h> int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,0 }; printf("%p\n", arr);//地址--首元素的地址 printf("%p\n", arr+1);//加4 printf("%p\n", &arr); printf("%p\n", &arr+1);//加40 //&arr-&数组名 //数组名不是首元素的地址-数组名表示整个数组 //&数组名取出的是整个数组的地址 //sizeof(arr)-sizeof(数组名)计算整个数组大小 printf("%p\n", &arr[0]); printf("%p\n", &arr[0]+1);//加4 return 0; }
#include <stdio.h> int main() { int arr[10] = { 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; }
六、 二级指针
#include<stdio.h> int main() { int a = 10; int * pa = &a; int* * ppa = &pa;//ppa为二级指针 //*ppa 通过对ppa中的地址解引用,找pa, *ppa 访问的是pa int** * pppa = &ppa;//pppa为三级指针 return 0; }
七、指针数组
是存放指针的数组
#include<stdio.h> 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", *(arr2[i])); } return 0; }