c语言之指针的学习

目录

1.指针是什么

2.指针和指针类型

3.野指针

如何避免野指针

4指针运算

指针+-(加减)整数. 

指针-(减)指针.

指针的关系运算

5.指针和数组

6.指针数组

1.指针是什么

(指针是内存中一个最小单元的编号,也就是地址)

int main()
{
    int a=10;//当我们取出地址a的时候,取出的其实是a占4个字节中的第一个字节的地址
    int *pa=&a;//pa是一个指针变量,用于存放地址
    //pa在口头语上常说为指针
    //指针本质上就是地址,口语上的指针是指针变量,用于存放地址
    reruen 0;
)

 (平时口语常说的指针,通常指的是指针变量,是用来存放内存地址的变量)

关于指针的大小的解释

//假设在32位的机器上经行编码,这个机器产生的地址之可能是
00000000 00000000 00000000 00000000//32个bit位 
00000000 00000000 00000000 00000001
......
11111111 11111111 11111111 11111111
共有2^32次方个地址,每一个地址能管理一个字节
经过换算2^32字节==4GB
可知在32位的机器上,地址是32个0或1组成的二进制序列,那地址就得用
4个字节的空间来储存,所以在一个指针变量的的大小是4个字节
同理,在64位的机器上,一个指针变量的大小为8个字节 
 ---------------------------------------------------------
例子
#include<stdio.h>
int main()
{
	char *pc=0;
	int *ps=0;
	double *pi=0;
	short *pd=0;
	printf("%d\n",sizeof(pc));
	printf("%d\n",sizeof(ps));
	printf("%d\n",sizeof(pi));
	printf("%d\n",sizeof(pd));
	return 0;
 } 
8
8
8
8

--------------------------------
Process exited after 0.07514 seconds with return value 0
请按任意键继续. . .

2.指针和指针类型

指针类型决定了指针在被解引用的时候访问几个字节

如果是int*型的指针,解引用访问4个字节;如果是char*型的指针,解引用访问1个字节(指针的类型决定指针变量访问的字节数或者说+1时跳过的字节数)

ps:int类型与float类型虽然所占用的字节大小一样,但是不能通用,

如果给int型的指针变量赋值100.0,则该指针变量的值不一定为100.0

#include<stdio.h>
int main()
{
	int a=0x11223344;
	char *pc=(char*)&a;//强制类型转换,避免一些编译器的问题
	int *ps=&a;
	printf("pc=%p\n",pc);
	printf("pc+1=%p\n",pc+1);
	printf("ps=%p\n",ps);
	printf("ps+1=%p\n",ps+1);
	return 0;
 } 
pc=000000000062FE0C
pc+1=000000000062FE0D
ps=000000000062FE0C
ps+1=000000000062FE10

--------------------------------
Process exited after 0.07891 seconds with return value 0
请按任意键继续. . .
//可知指针的类型决定了指针加一减一操作的时候,跳过几个字节

3.野指针

概念:(指针指向的位置时不可知的)

例如
int main()
{
    int *p;//p没用初始化,意味着没有明确的方向
    *p=10;//非法访问内存,局部变量不进行初始化存放的时随机值
    return 0;
}
---------------------------------
指针的越界访问
int main()
{
	int arr[10]={0};
	int *p;
	int i=0;
	for(i=0;i<=10;i++)
	{
		*p=i;
		p++;
	}
	return 0;
 } 
--------------------------------
例
#include<stdio.h>
int *test()
{
	int a=10;
	return &a;//a在函数调用后还给操作系统了,在本程序中
没有该空间使用权限,a在内存的空间还在
}
int main()
{
	int *p=test();//函数运行结束后调用*p,则*p成为野指针 
    printf("%d\n",*p);//虽然调用后没有使用权限了,但在a原来的地址没用被占用
之前,还能通过*p找到a的地址与值
	return 0;
 } 
-----------------------------------------
为了避免野指针的出现,对于暂时不知道赋值为什么的指针我们可以赋值为NULL
如何避免野指针

1.指针初始化

2.注意指针越界

3.避免返回局部变量的地址

4.指针指向NULL

5.检测指针的有效性

4指针运算

指针+-(加减)整数. 
指针-(减)指针.
//指针+指针没有意义
#include<stdio.h>
int main()
{
	int arr[10]={0};
	printf("%d\n",&arr[9]-&arr[0]);//指针-指针得到的是指针和指针之间的元素的个数
	return 0;//指向同一块空间的2个指针才能相减
 } 
9

--------------------------------
Process exited after 0.07593 seconds with return value 0
请按任意键继续. . .

例题:用指针-指针实现strlen函数
#include<stdio.h>
int my_strlen(char* str){
	char *str1=str;
	while(*str!='\0')
	{
		str++;
	}
	return (str-str1);
}
int main()
{
	char arr[10]={"abcdefg"};
	int len=my_strlen(arr);
	printf("%d\n",len);
	return 0;
 } 
7

--------------------------------
Process exited after 0.07583 seconds with return value 0
请按任意键继续. . .
指针的关系运算
#define N_VALUES 5
float values[N_VALUES];
float *v;
for(v=&values[0];v<&values[N_VALUES];)//v小于&values[N_VALUES]的地址
{
    *v++=0;//该行代码可分为两步理解1.*v=0  2.v++
}//值得注意的是,虽然N_VALLUES的下标值有到5,但是内存中有接下来的内存,所以在里不存在野指针
-------------------------------------------------
int main()
{
	int arr[10]={0};
	int i=0;
	int *p=arr;
	int sz=sizeof(arr)/sizeof(arr[0]);
	for(i=0;i<10;i++)
	{
		*p=1;// +
*(p+1)=1;
		p++;
	}	 
	return 0;
 } 

5.指针和数组

ps:数组是一组相同类型元素的集合

##include<stdio.h>
//数组可以通过指针来访问 
int main()
{
	char arr[10]={"abcdefg"};
	//数组名表示首元素的地址 
	char* len=arr;
//但是数组就是数组,指针就是指针
    int sz=sizeof(arr)/sizeof(arr[0]);
    for(char i=0;i<sz;i++){
    	printf("%c\n",*(len+i));
	}
	return 0;
 } 
a
b
c
d
e
f
g




--------------------------------
Process exited after 0.0759 seconds with return value 0
请按任意键继续. . .
---------------------------------------------------------------------------

#include<stdio.h>
//数组可以通过指针来访问 
int main()
{
	char arr[10]={"abcdefg"};
	//数组名表示首元素的地址 
	char* len=arr;
//但是数组就是数组,指针就是指针
    int sz=sizeof(arr)/sizeof(arr[0]);
    for(char i=0;i<sz;i++){
    	printf("%p--------%p\n",&arr[i],len+i);//
	}
	return 0;
 } 
000000000062FE00--------000000000062FE00
000000000062FE01--------000000000062FE01
000000000062FE02--------000000000062FE02
000000000062FE03--------000000000062FE03
000000000062FE04--------000000000062FE04
000000000062FE05--------000000000062FE05
000000000062FE06--------000000000062FE06
000000000062FE07--------000000000062FE07
000000000062FE08--------000000000062FE08
000000000062FE09--------000000000062FE09

--------------------------------
Process exited after 0.07819 seconds with return value 0
请按任意键继续. . .

6.二级指针

ps:指针的类型为定义该指针的表达式-该指针的名字

总而言之,二级指针是用来存放一级指针变量的地址(这个地址是一级指针变量的地址)

#include<stdio.h>
int main()
{
	int a=10;
	int *p=&a;//p是一个指针变量,是一级指针
	int **pp=&p;//pp是一个二级指针 
	//*p=20;一级指针对变量的修改 
	**pp=20//二级指针对变量的修改 
	printf("%d\n",p); 
	return 0;
 } 

7.指针数组

指针数组即存放指针的数组

#include<stdio.h>
int main()
{
	int a=10;
	int b=20;
	int c=30;
	int i=0; 
	//int *pa=&a;
    //int *pb=&b;
	//int *pc=&c; 
	int *prr[10]={&a,&b,&c};//prr是一个指针数组 
	for(i=0;i<10;i++)
	{
		printf("%p\n",prr[i]);
	}
	return 0;
 } 
000000000062FE08
000000000062FE04
000000000062FE00
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000

--------------------------------
Process exited after 0.08151 seconds with return value 0
请按任意键继续. . .
------------------------------------------------------------------------------------
#include<stdio.h>
int main()
{
	int a=10;
	int b=20;
	int c=30;
	int i=0; 
	//int *pa=&a;
    //int *pb=&b;
	//int *pc=&c; 
	int *prr[10]={&a,&b,&c};//prr是一个指针数组 
	for(i=0;i<10;i++)
	{
		printf("%d\n",*prr[i]);
	}
	return 0;
 } 
10
20
30

--------------------------------
Process exited after 0.3447 seconds with return value 3221225477
请按任意键继续. . .

例题

#include<stdio.h>
int main()
{//用指针数组模拟二维数组
    int arr1[4]={1,2,3,4};
	int arr2[4]={2,3,4,5}; 
	int arr3[4]={3,4,5,6};
	int *parr[3]={arr1,arr2,arr3};
	int i=0;
	for(i=0;i<3;i++)
	{
		int j=0;
		for(j=0;j<4;j++)
		{
			printf("%d",parr[i][j]);
		}
		printf("\n");
	}
	return 0;
 } 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值