目录
1. 指针是什么
2. 指针和指针类型
3. 野指针
4. 指针运算
5. 指针和数组
6. 二级指针
7. 指针数组
指针理解的2个要点:
1. 指针是内存中一个最小单元的编号,也就是地址
2. 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量
总结:指针就是地址,口语中说的指针通常指的是指针变量。
#include<stdio.h> int main() { int a = 10; int* pa = &a; //pa是指针变量 printf("%d\n", sizeof(pa)); // 4 // printf("%p\n", &a); // 00000000 00000000 00000000 00001010 // 00 00 00 0a return 0; }
我们可以通过&(取地址操作符)取出变量的内存其实地址,把地址可以存放到一个变量中,这个 变量就是指针变量
在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储,所以 一个指针变量的大小就应该是4个字节。
那如果在64位机器上,如果有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地 址。
总结: 指针是用来存放地址的,地址是唯一标示一块地址空间的。 指针的大小在32位平台是4个字节,在64位平台是8个字节。
#include<stdio.h> int main() { char* pc; int* pa; double* pd; printf("%d\n",sizeof(pc)); // 4 printf("%d\n", sizeof(pa)); // 4 printf("%d\n", sizeof(pd)); // 4 return 0; }
指针作用1:指针类型决定了在解引用时能访问几个字节(指针的权限)
#include<stdio.h> int main() { int a = 0x11223344; int* pa = &a; *pa = 0; char* pc = &a; *pc = 0; // 指针类型决定了在解引用的时候以此能访问几个字节(指针的权限) // int* --> 4 // char* --> 1 // double* --> 8 return 0; }
指针作用2:指针类型决定了//指针作用2:指针类型决定了指针向前或者向后走一步,走多大距离(单位是字节)
#include<stdio.h> int main() { int a = 10; int* pa = &a; char* pc = &a; printf("%p\n", pa); //001EFE54 printf("%p\n", pa + 1); //001EFE58 printf("%p\n", pc); //001EFE54 printf("%p\n", pc + 1); //001EFE55 return 0; }
例如:
创建一个整型数组,10个元素
1:初始化数组的内容是1-10
2:打印数组
#include<stdio.h> int main() { int arr[10] = { 0 }; int* p = arr; int i = 0; for (i = 0; i < 10; i++) { *(p + i) = i+1; } // 倒着打印 int* q = &arr[9]; for (i = 0; i < 10; i++) { printf("%d ", *q); // 10 9 8 7 6 5 4 3 2 1 q--; } return 0; }
概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
成因:
#include<stdio.h> int main() { /*int a; printf("%d\n", a);*/ //未初始化 //int* p; //野指针 //*p = 20; //越界访问 int arr[10] = { 0 }; int* p = arr; int i = 0; for (i = 0; i <= 10; i++) { *p = i; p++; } return 0; }
1. 指针初始化
2. 小心指针越界
3. 指针指向空间释放即使置NULL
4. 避免返回局部变量的地址 5. 指针使用之前检查有效性
#include<stdio.h> int* test() { int a = 100; return &a; } int main() { int* p = test(); printf("%d\n", *p); // 100 return 0; }
// 指针指向空间及时放置NULL #include<stdio.h> int main() { int* p = NULL; if (p != NULL) { *p = 100; } int arr[10] = { 0 }; int* q = arr; q = NULL; return 0; }
#include<stdio.h> int main() { int arr[10] = { 0 }; int* p = arr; int i = 0; int sz = sizeof(arr) / sizeof(arr[0]); for (i = 0; i < sz; i++) { *(p + i) = i + 1; } for (i = 0; i < sz; i++) { printf("%d ", *(p + i)); // 1 2 3 4 5 6 7 8 9 10 } return 0; }
倒着打印:
#include<stdio.h> int main() { int arr[10] = { 0 }; int* p = arr; int i = 0; int sz = sizeof(arr) / sizeof(arr[0]); for (i = 0; i < sz; i++) { *(p + i) = i + 1; } int* q = &arr[sz - 1]; //int* q = arr + sz - 1; for (i = 0; i < sz; i++) { printf("%d ", *q); // 10 9 8 7 6 5 4 3 2 1 q--; } return 0; }
指针减指针
#include<stdio.h> int main() { int a[10] = { 0 }; printf("%d\n", &a[9] - &a[0]); // 9 printf("%d\n", &a[0] - &a[9]); // -9 return 0; } //相减的前提是两块指针指向同一块空间 #include<stdio.h> int main() { int a = 10; char c = 'w'; &a - &c; // 编译器报错,不能不同类型指针相加减 return 0; }
求字符串长度(拓展)指针-指针
#include<stdio.h> #include<string.h> int my_strlen(char* s) { char* start = s; while (*s != '\0') { s++; } return s - start; } int main() { char arr[] = "abc"; int len = my_strlen(arr); printf("%d\n", len); // 3 return 0; }
#include<stdio.h> int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int* p = arr; int i = 0; int sz = sizeof(arr) / sizeof(arr[0]); /*for (i = 0; i < 10; i++) { printf("%p==%p\n", p + i, &arr[i]); }*/ for (i = 0; i < 10; i++) { printf("%d ", p[i]); // 1 2 3 4 5 6 7 8 9 10 } return 0; }
指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里? 这就是 二级指针
#include<stdio.h> int main() { int a = 10; int* pa = &a; int** ppa = &pa; //ppa就是一个二级指针 int*** pppa = &ppa;//pppa就是一个三级指针 //***pppa = 20; *pa = 20; printf("%d\n", a); return 0; }
#include<stdio.h> int main() { int arr[10]; //整型数组,存放整形的数组 char ch[5]; //字符数组,存放字符的数组 //指针数组,存放指针的数组 int a = 10; int b = 20; int c = 30; int* arr2[5] = { &a,&b,&c }; //存放整形指针的数组 int i = 0; for (i = 0; i < 5; i++) { printf("%d ", *(arr2[i])); // 10 20 30 } return 0; }
指针数组是指针还是数组?
答案:是数组。是存放指针的数组。
数组我们已经知道整形数组,字符数组。
那指针数组是怎样的?
arr3是一个数组,有五个元素,每个元素是一个整形指针。