指针初识总结

目录

一.什么是指针

 二.指针和指针类型

 1.指针类型

 2.指针的定义

 3.解引用运算符:*

 4.指针类型的意义

          (1).访问字节的大小

          (2).指针加减整数时位移的大小

  5.野指针(是错误的指针用法)

 野指针成因

三.指针的运算

  1. 指针+-整数

  2.指针减去指针  

 应用

  3.指针的关系运算

四. 指针与数组

  1.数组名是什么?

数字组可通过指针来访问

五. 二级指针

五.指针数组


一.什么是指针


   在计算机科学中,指针(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 };//指针数组,用来存放指针
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

binary~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值