1.指针是什么?
指针是内存中一个最小单元的编号,也就是地址
平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量
总结:指针就是地址,口语中说的指针通常指的是指针变量
// 指针是什么?
// 1.指针是内存中一个最小单元的编号,也就是地址
// 2.平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量
// 总结:指针就是地址,口语中说的指针通常指的是指针变量
int main()
{
int a = 100; //在内存中开辟一块空间
int * pa = &a; //pa是专门来存放地址(指针)的,pa在这里就被称为指针变量
//这里我们对变量a,取出它的地址,可以使用&操作符
//a变量占用4个字节的空间,这里是将a的4个字节的第一个字节的地址存放在p变量中,p就是一个指针变量
// int arr[10];
// printf("%p\n",&a);
printf("%p\n",pa);
return 0;
}
2.指针和指针类型
int* 的指针解引用访问4个字节
char* 的指针解引用访问1个字节
结论:指针类型可以决定指针解引用的时候访问多少个字节(指针的权限)
int* 4个字节 char* 1个字节 short* 2个字节 float* 4个字节 double* 8个字节
//指针类型的意义
int main()
{
int a = 0x11223344; //0x开头是16进制数字
//int * pa = &a;
char * pa = &a;
// int* 的指针解引用访问4个字节
// char* 的指针解引用访问1个字节
// 结论:指针类型可以决定指针解引用的时候访问多少个字节(指针的权限)
*pa = 0;
return 0;
}
//type * p *说明p是指针变量
//1. p指向的对象的类型
//2. p解引用的时候访问的对象大小是sizeof(type)
int main()
{
int a = 0x11223344; //0x开头是16进制数字
int* pa = &a;
char* pc = &a;
printf("%p\n",pa); //0x16d207388
printf("%p\n",pc);//0x16d207388
//int * 增加4个字节,char * 增加1个字节
printf("%p\n",pa+1); //0x16d20738c
printf("%p\n",pc+1);//0x16d207389
//指针类型决定指针+1/-1操作时的步长
//整形指针+1跳过4个字节
//字符指针+1跳过1个字节
return 0;
}
3.野指针
//野指针
// int main()
// {
// int a = 10;
// int* pa = &a;
// *pa = 20;
// printf("%d\n",a);
// return 0;
// }
//p是野指针 野指针就是指针指向的位置是不可知的(随机的,不正确的,没有明确限制的)
// int main()
// {
// int* p; //局部变量不初始化的时候,内容是随机值
// *p = 20;
// printf("%d\n",*p);
// return 0;
// }
//指针越界访问
// int main()
// {
// int arr[10] = {0};
// int* p = arr;
// int i = 0;
// for(i = 0; i<= 11;i++)
// {
// //当指针指向的范围超出数组arr的范围时,p就是野指针
// *(p++) = i;
// }
// return 0;
// }
//指针释放
int* test()
{
int a = 110;
return &a;
}
int main()
{
int* p = test();
printf("%d\n",*p);
return 0;
}
如何规避野指针:
1指针初始化
2小心指针越界
3指针指向的空间释放,及时置NULL
4避免返回局部变量的地址
5指针使用之前检查有效性
// 如何规避野指针:
// 1指针初始化
int main()
{
int a = 0;
int* p = &a;
int* ptr = NULL; //告诉你ptr是一个空指针,没有指向任何有效的空间,这个指针不能直接使用
int* ptr2; //野指针
if (ptr != NULL)
{
//使用
}
return 0;
}
// 2小心指针越界
// 3指针指向的空间释放,及时置NULL
// 4避免返回局部变量的地址
// 5指针使用之前检查有效性
4.指针运算
指针+ - 整数
//指针运算
// int main()
// {
// int arr[10] = {0};
// //不使用下标访问数组
// int* p = &arr[0];
// int i = 0;
// int sz = sizeof(arr)/sizeof(arr[0]);
// for (int i = 0; i < sz; i++)
// {
// *p = i;
// p++; // p = p+1
// }
// p = arr;
// for (i = 0; i < sz; i++)
// {
// printf("%d ",*(p+i)); // p+i
// }
// // for (i = 0; i < 10; i++)
// // {
// // printf("%d",arr[i]);
// // }
// return 0;
// }
//int arr[10];
//int* p = arr;
//*(p+i) == arr[i]
//*(arr+i) == arr[i]
//数组名是首元素的地址 -- 指针
//arr[i] == *(arr+i) == *(i+arr) == i[arr]
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int i = 0;
int *p = arr;
for(i = 0;i < 10; i++)
{
printf("%d ",i[arr]); //[]操作符
printf("%d ",*(p+i)); //[]操作符
}
//arr[i] --> i[arr]
return 0;
}
// int my_strlen(char* s)
// {
// int count = 0;
// while (*s != '\0')
// {
// count++;
// s++;
// }
// return count;
// }
//递归实现
// int my_strlen(char* s)
// {
// if (*s == '\0')
// {
// return 0;
// } else
// {
// return 1 + my_strlen(s + 1);
// }
// return 0;
// }
int my_strlen(char* s)
{
char* start = s;
while (*s != '\0') //(*s)
{
s++;
}
// while (*s++); //err
//while (*s++); return s -start-1; //true
return s -start;
}
int main()
{
char arr[] = "abcdef"; // a b c d e f \0
int len = my_strlen(arr);
printf("%d\n",len);
return 0;
}
5.指针和数组
//指针和数组之间是什么关系呢?
//指针变量就是指针变量,不是数组,指针变量的大小是4/8个字节,专门是用来存放地址的
//数组就是数组,不是指针,数组一块连续的空间,可以存放一个或者多个类型相同的数据
//指针和数组之间的关系:数组中,数组名其实是数组首元素的地址,数组名 == 地址 == 指针
//当我们知道数组首元素的地址的时候,因为数组又是连续存放的,使用通过指针就可以遍历访问数组,数组是可以通过指针访问的
// 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("%p == %p\n",p+i,&arr[i]);
// }
// return 0;
// }
// int main()
// {
// int a = 10;
// int* p = &a;//p是一级指针变量,指针变量也是变量,变量是在内存中开辟空间的
// int** pp = &p; //pp就是二级指针,二级指针变量就是用来存放一级指针变量的地址
// *(*pp) = 100;
// *p = 10;
// int** * ppp = &pp;
// //int* 是在说明pp指向的是int*类型的变量
// printf("%d\n",a);
// printf("%p\n",&a);
// printf("%p\n",&p);
// printf("%p\n",pp);
// return 0;
// }
6.二级指针
// int main()
// {
// int a = 10;
// int* p = &a;//p是一级指针变量,指针变量也是变量,变量是在内存中开辟空间的
// int** pp = &p; //pp就是二级指针,二级指针变量就是用来存放一级指针变量的地址
// *(*pp) = 100;
// *p = 10;
// int** * ppp = &pp;
// //int* 是在说明pp指向的是int*类型的变量
// printf("%d\n",a);
// printf("%p\n",&a);
// printf("%p\n",&p);
// printf("%p\n",pp);
// return 0;
// }
int main()
{
char arr1[] = "abcdef";
char arr2[] = "hello world";
char arr3[] = "xiaofan";
char* parr[] = {arr1,arr2,arr3};
int i = 0;
int sz = sizeof(parr)/sizeof(parr[0]);
char** p = parr;
for (i = 0;i<sz;i++)
{
//printf("%s\n",parr[i]);
printf("%s\n",*(p+i));
}
//**p = '1111';
//printf("%s\n",parr[0]);
return 0;
}
7.指针数组
//指针数组
//指针数组是指针还是数组 是数组,是存放指针的数组 数组我们已经知道整形数组,字符数组
//整型数组 -存放整型的数组 字符数组 - 存放字符的数组 指针数组-存放指针(地址)的数组
int main()
{
// char arr[] = "abcdef";
// printf("%s\n",arr);
int arr1[] = {1,2,3,4,5};
int arr2[] = {2,3,4,5,6};
int arr3[] = {3,4,5,6,7};
//指针数组
int* parr[] = {arr1, arr2, arr3};
int i = 0;
for(i = 0;i<3;i++)
{
int j = 0;
for(j = 0;j <5;j++)
{
//printf("%d ",parr[i+j]);//err
printf("%d ",*(parr[i]) + j);
// printf("%d ",parr[i][j]);
}
printf("\n");
}
return 0;
}