目录
一.什么是指针
在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向(pointers to)存在电脑储存器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”。意思是通过它能找到以它为地址的内存单元。
#include<stdio.h>
int main()
{
int a = 3; //在内存中开辟一片空间
int* p = &a;//对变量a进行取地址,可以使用&操作符
//将a的地址存在p里面,则p就是一个指针变量
return 0;
}
总结:指针就是地址,地址就是指针
二.指针和指针类型
1.指针类型
变量有不同类型,当然指针也有不同类型,比如:整型指针,浮点型指针等
2.指针变量的定义
指针的定义形式如:数据类型*指针名;例如:
//分别定义了char,int,short,double类型的指针变量
char* a;
int* b;
short* c;
double* d;
3.解引用运算符:*
解引用运算符 * 可将存在某地址中的信息取出来
#include<stdio.h>
int main()
{
int a = 30;
int* p = &a;
printf("%p\n", p);
printf("%d\n", *p);//此处的*p就使用了解引用操作
}
结果
使用此操作符,将存在地址p中的30取了出来
4.指针类型的意义
让我们看一下下面几段代码及结果
#include<stdio.h>
int main()
{
printf("%d\n", sizeof(char*));
printf("%d\n", sizeof(short*));
printf("%d\n", sizeof(int*));
printf("%d\n", sizeof(double*));
return 0;
}
结果
#include<stdio.h>
int main()
{
int a = 3;
char* pa = &a;
int* pc = &a;
printf("%p\n", pa);
printf("%p\n", pc);
printf("%p\n", pb);
printf("%p\n", pd);
return 0;
}
结果
通过两组代码及结果看出,不同类型的指针所执行出来的结果相同。看似不同类型指针的意义 相同,但其实不是这样的,下面让我们看看不同类型指针的意义。
(1).访问字节的大小
使用int*指针
#include<stdio.h>
int main()
{
int a = 0x11223344;
int* p = &a;
*p = 0;
}
若使用char*
#include<stdio.h>
int main()
{
int a = 0x11223344;
char* p = &a;
*p = 0;
}
结论:指针类型决定了指针进行解引用操作的时候,能够访问空间的大小
int* p;*p能够访问4个字节
char* p;*p能够访问1个字节
double* p;*p能够访问8个字节
(2).指针加减整数时位移的大小
#include<stdio.h>
int main()
{
int a = 0x11223344;
int* pa = &a;
char* pc = &a;
printf("%p\n", pa);
printf("%p\n", pa+1);
printf("%p\n", pc);
printf("%p\n", pc+1);
return 0;
}
结论
指针类型决定了,指针走一步走多远(指针的步长)
int*p; p+1走向后4个字节
char*p;p+1向后走1个字节
double*平;p+1向后走8个字节
5.野指针(是错误的指针用法)
概念:指针指向的位置不可知(随机的,不正确的,没有明确限制的)
野指针成因
1,指针未初始化
#include<stdio.h>
int main()
{
int* a;//局部变量未初始化,默认为随机
*a = 20;
return 0;
}
2,指针越界访问
#include<stdio.h>
int main()
{
int arr[10] = { 0 };
int* p = arr;
int i = 0;
for (i = 0; i < 12; i++)//当i>10后就会发生指针越界,出现野指针;
p++;
}
3,指针指向的的空间释放
#include<stdio.h>
int* test()
{
int a = 10;
return &a;
}
//当出test这个函数后在函数内部的函数就会被销毁。
int main()
{
int* p = test();
*p = 20; //要访问的空间已被销毁,会随机产生地址,出现野指针
return 0;
}
如何避免野指针
1.指针初始化
2.小心指针越界
3.指针指向空间释放即使置为空
4.指针使用之前检查指针检查有效性
三.指针的运算
1. 指针+-整数
例子:
#include<stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
int* p = &arr;
int sz = sizeof(arr) / sizeof(arr[0]);//计算数组元素个数
for (i = 0; i < sz; i++)
{
printf("%d ", *p);
p++; //每次指针加1
}
}
结果:
减法同理
2.指针减去指针
指针减去指针得到的值的绝对值其实是两地址中间元素的个数
例如1:
#include<stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("%d", &arr[9] - &arr[0]); //指针减去指针
}
结果:
分析:
例如2:
#include<stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("%d", &arr[0] - &arr[9]); //指针减去指针
}
结果:
注意:指针减指针时,这两个指针必须是指向同一块空间的,比如:同一个数组。
应用
写一个函数模拟strlen函数的功能
#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[] = "apple"; //存在数组中的元素为 'a','p','p','l','e','\0'
int len = my_strlen(arr);
printf("%d", len);
}
结果:
3.指针的关系运算
指针关系运算就是指比大小
#include<stdio.h>
#define N 5 //宏
int main()
{
int arr[N] = { 1,1,1,1,1 };
int* p;
for (p = &arr[N]; p > &arr[0];) //进行指针大小比较
{
*--p=0;
}
int i = 0;
for (i = 0; i < N; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
结果:
分析:
四. 指针与数组
1.数组名是什么?
#include<stdio.h>
int main()
{
int arr[5] = { 0 };
printf("%p\n", arr); //打印数组名地址
printf("%p\n", &arr[0]); //打印数组首元素地址
}
结果:
由结果看出,两个地址相同所以可以得出结论 :数组名绝大多数情况下指的是首元素地址
例外:
1.&arr ——&数组名 ,数组名不是首元素的地址-此情况下数组名表示整个数组,&数组名 取出的是整个数组的地址。
整个数组的地址与首元素的地址数值上相同,但表示的意义完全不同。分析如下:
2.sizeof(arr)——sizeof(数组名)此情况下数组名表示整个数组,sizeof(arr)计算的是整个数组的大小。
数字组可通过指针来访问
指针访问的是数组首元素地址
#include<stdio.h>
int main()
{
int i = 0;
int arr[5] = { 1,2,3,4,5 };
int* p = &arr; //访问首元素地址
for (i = 0; i < 5; i++)
{
printf("%d ", *(p + i));
}
}
结果:
五. 二级指针
#include<stdio.h>
int main()
{
int a = 3;
int* pa = &a;
int** ppa = &pa;//二级指针存放的是pa的地址,及存放a地址的地址
}
如上面例子,二级指针存放的是pa的地址,及存放a地址的地址
当然也有三级指针,四级指针等
#include<stdio.h>
int main()
{
int a = 3;
int* pa = &a;
int** ppa = &pa;//二级指针存放的是存放pa的地址,及存放a地址的地址
int*** pppa = &ppa;//三级指针
int**** ppppa = &pppa;//四级指针
}
后面以此类推。
五.指针数组
指针数组本质是一个数组
是一个存放指针的数组
#include<stdio.h>
int main()
{
int a = 3;
int b = 5;
int c = 8;
int* arr[] = { &a,&b,&c };//指针数组,用来存放指针
}