指针

时间:2023-02-06 17:03:09

1.指针是什么

在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向(polnts to)存在电脑存储器中另一个地方的值,由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为”指针”。意思是通过它能找到以它为地址的内存单元。

指针是一个变量,变量里面存放的是地址。可以理解为 指针就是地址

int* p=&a;//p是指针变量,&a是地址

指针的定义是内存地址,而指针变量是用来存放内存地址的一个变量。

注:1.在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储,所以一个指针变量的大小就应该是4个字节;那如果在64位机器上,如果有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地址

总结:指针是用来存放地址的,地址是唯一标示一块地址空间的;指针的大小在32位平台是4个字节,在64位平台是8个字节

指针和指针类型

#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;
}

指针

但虽然指针的大小都是4/8个字节 但类型仍有一定作用

(变量的指针包含编号表示的纯地址和它指向的储存单元)

区别1:

int a=0x11223344;//11一个字节 22一个字节 33一个字节 44一个字节
int* pa=&a;//&a取出a的地址,放入pa里,pa作为一个存放地址的变量需要用到指针,则产生了int*
char* pc=&a;
printf("%p\n",pa);
printf("%p\n",pc);
return 0;
}

补:2个16进制位=8个2进制位=1个字节

此代码由于占四个字节 则printf("%p\n",pc);无法执行(放不下)

区别2:

int a=0x11223344;
int* pa=&a;
*pa=0;

a地址的值会变成00000000,因为int能访问四个字节的便改变了四个字节单位

int a=0x11223344;
char* pc=&a;
*p=0;

a的地址变为了00332211,因为char只访问一个字节

指针类型意义1:决定了指针进行解引用操作的时候,能够访问空间的大小

所以 指针需要选用合适的类型去使用

指针类型意义2:指针+-整数:决定了一步向前或向后走了多少字节(指针的步长)

int a=0x11223344;
int* pa=&a;
printf("%p\n",pa);
printf("%p\n",pa+1);//int 地址在pa的类型上跳了一个int类型 也就是跳了四个字节

2.野指针

指针指向的位置是不可知的(随机的 不正确的 没有明确限制的,就像野猫野狗一样)

1.不初始化

int a;//局部变量不初始化 默认随即值
int *p;//局部的指针变量不初始化 就被初始化为随机值
*p=20;//随便存的位置 你我都不知道

2.指针越界访问

#include<stdio.h>
int main()
{
int arr[10]={0};//是个空间
int* p=arr;
int i;
for(i=0;i<12;i++)//循环12次
{
p++;
}
//越出能管理的范围内
return 0;
}

3.空间被释放

相当于你曾经拥有过一个好朋友的电话号码 但是打过去却是空号

#include<stdio.h>
int* test()
{
int a=10;//局部变量
return &a;
}
int main()
{
int* p=test();//a空间已经被释放了
*p=20;
return 0;
}

规定:指针要初始化;小心指针越界;指针指向空间释放设置NULL;指针使用前检查有效性

3.指针运算

指针+-整数

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;//地址
}

指针-指针

这种指针的运算必须是同一个指针内的

得到中间的元素个数--9

int arr[10]={1,2,3,4,5,6,7,8,9,10};
printf("%d\n",&arr[9]-&arr[0]);

指针的关系运算(比地址大小)

规定:能向右越界 不能向左越界

#define N_VALUSE 5
float values[N_VALUSE]
float* vp;
for(vp=&value[N_VALUSE];vp>=&value[0];)
{
*--vp=0;
}

不推荐以下代码

#define N_VALUSE 5
for(vp=&value[N_VALUSE-1];vp>=&value[0];vp--)
{
*vp=0;
}

4.指针与数组

#include<stdio.h>
int main()
{
int arr[10]={0};
printf("%p\n",arr);//首元素地址
printf("%p\n",&arr[0]);//首元素地址
printf("%p\n",&arr);//整个数组的地址(从起始位置-首元素-开始)
//1. &arr &数组名 数组名不是首元素的地址-数组名表示整个数组,取出的是整个数组的地址
//2. sizeof(arr) sizeof(数组名)-数组名表示的是整个数组,计算的是整个数组的大小
return 0;
}

区别

#include<stdio.h>
int main()
{
int arr[10]={0};
printf("%p\n",arr);//首元素地址
printf("%p\n",arr+1);//+4

printf("%p\n",&arr[0]);//首元素地址
printf("%p\n",&arr[0]+1);//+4

printf("%p\n",&arr);//整个数组的地址(从起始位置-首元素-开始)
printf("%p\n",&arr+1);//+4*10
return 0;
}

指针

所以说数组是可以通过指针来访问的

一个打印指针,一个打印取地址。虽然方式不一样但都是访问了地址

#include<stdio.h>
int main()
{
int arr[10]={0};
int* p=arr;
int i=0;
for(i=0;i<10;i++)
{
printf("%p ===== %p\n",p+i,&arr[i]);
}
return 0;
}

指针

5.二级指针

存放指针变量地址的指针变量

int a=10;
int* pa=&a;//pa一级指针变量 int*一级指针类型。变量的创建也需要在内存中开辟空间
int** ppa=&pa;//ppa就是二级指针
int*** pppa=&ppa;

应用:通过解引用找到原来的地址内容

int a=10;
int* pa=&a;
int* * ppa=&pa;
*ppa//得到pa的地址内容
* *ppa//对*ppa(也就是对pa)进行解引用操作 得到a的地址内容

6.指针数组

指针数组是存放指针的数组

数组指针是指向数组的指针

#include<stdio.h>
int main()
{
int a=10;
int b=20;
int c=30;

int* pa=&a;
int* pb=&b;
int* pc=&c;
//整型数组-存放整型
//字符数组-存放字符
//所以
//指针数组-存放指针

int* arr[3]={&a,&b,&c};//指针数组
int i=0;//下标
for(i=0;i<3;i++)
{
printf("%d\n",*(arr[i]));
}
return 0;
}

指针