#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
指针:
标准规定:
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,
但是不允许与指向第一个元素之前的那个内存位置的指针进行比较
一.指针是什么
内存编号 - 地址 - 指针
int main()
{
int a = 10; //a占4个字节
int* pa = &a; //拿到的是a的4个字节中第一个字节的地址
return 0;
}
二.指针和指针类型
指针类型的意义:
指针类型决定了:①指针解引用的权限有多大
②指针走一步,能走多远(多长)
①:
int main()
{
0 1 2 3 4 5 6 7 8 9 a b c d e f
11111111
8421 - 4个2进制位可以表示1个16进制位
int a = 0x11223344; // 1个字节就可以表示2个16进制位
char* pc = &a;
*pc = 0; //只有第一个字节变为0
int* pa = &a;
*pa = 0; //四个字节都变为0
return 0;
}
②:
int main()
{
int arr[10] = { 0 };
int* p = arr;
char* pc = arr;
不管放什么类型的指针都能存放地址
printf("%p\n", p);
printf("%p\n", p+1); //加了4
printf("%p\n", pc);
printf("%p\n", pc+1); //加了1
return 0;
}
int main()
{
int arr[10] = { 0 };
int* p = arr;
int i = 0;
for (i = 0;i < 10;i++)
{
*(p + i) = 1; // p + i 其实是下标位i的地址
}
return 0;
}
三.野指针
概念:野指针就是指针指向的位置是不可知的(随机的,不正确的,没有明确限制的)
成因:①指针未初始化
int main()
{
//这里的p就是一个野指针
int* p; //p是一个局部的指针变量,局部变量不初始化的话,默认是随机值
*p = 20; //非法访问内存了
return 0;
}
②指针越界访问
int main()
{
int arr[10] = { 0 };
int* p = arr;
int i = 0;
for (i = 0;i <= 10;i++)
{
*p = i;
p++;
}
return 0;
}
③指针指向空间释放
int* test()
{
int a = 10;
return &a;
}
int main()
{
int* p = test();
*p = 20;
return 0;
}
如何避免野指针?
1.指针初始化 ps:当不知到指针初始话为什么地址的时候,直接初始化为NULL
2.小心指针越界 ps:C语言本身是不会检查数据的越界行为的
3.指针指向空间释放及时置NULL ps:UNLL是不能直接使用它的
4.指针使用之前检查有效性 ps: if(p != NULL)来检查有效性
四.指针运算
1.指针 +- 整数
int main()
{
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++;
}
return 0;
}
2.指针 - 指针 得到的两个指针之间的元素个数
指针和指针相减的前提:两个指针指向同一块空间
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
char c[5];
printf("%d\n", &arr[9] - &arr[0]);
return 0;
}
计数器的方法
int my_strlen(char* str)
{
int count = 0;
while (*str != '\0')
{
count++;
str++;
}
return count;
}
指针减指针的方法
int my_strlen(char* str)
{
char* start = str;
while (*str != '\0')
{
str++;
}
return str - start;
}
int main()
{
//strlen(); - 求字符串长度
//int len = strlen("abc");
char arr[] = { "abc" };
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
五:指针和数组
int main()
{
int arr[10] = { 0 };
int* p = arr; //数组名
//[ ] 是一个操作符 2和arr是两个操作数
printf("%d\n", 2[arr]);
printf("%d\n", arr[2]);
printf("%d\n", p[2]); //p[2] --> * (p + 2)
//arr[2] --> * (arr + 2) --> * 2[arr]
//arr[2] <==> * (p + 2) <==> * (2 + p) <==> * (2 + arr)
//2[arr] <==> * (2 + arr)
return 0;
}
六:二级指针
int main()
{
int a = 10;
int* pa = &a; //pa是指针变量,一级指针
//ppa就是一个二级指针变量
int** ppa = &pa; //pa也是个变量,&pa取出pa再内存中起始地址
return 0;
}
指针数组 - 本质是数组
存放的是指针的数组