C语言深入理解指针(1)

一、内存和地址

1、内存

内存是电脑上的一块存储区域,可读可写,速度较快,关机时就会清空,可以跟CPU直接进行运算,内存的每个内存单元为一个字节
一个字节由八个比特位存储
一个比特可以存放一个二进制的位1或位0.
内存在使用时分为:
栈区、堆区、静态区。

2、地址

每个内存单元都有一个固定的地址,不需要保存,就像钢琴的每个键固定发出特定的声音,不需要在上面做标记,这是对一个懂钢琴的人来说的。
内存的每个单元都是有对应的地址,电脑自己知道每个地址在哪里。
CPU通过地址地址来编址的,在64位机器中地址用八个字节表示,32位机用4个地址表示。
CPU通过数据总线和控制总线共同和地址总线完成操作。
在C语言中,也引入了地址这个概念,用指针这个词来表示。
地址 <==>指针

二、指针变量和地址

1、指针变量

指针变量的值是地址,指针变量在创建时有:
指针变量类型 * 变量名
* 星号表示这个变量是指针

#include<stdio.h>
int main()
{
	int* p;
	return 0;
}

创建了一个变量名称为p的int*类型的指针变量
此时指针p没有存放仍会值

2、取地址&

指针变量存放的是地址
用&取地址操作符可以取出地址

#include<stdio.h>
int main()
{
	int* p;
	int a = 10;
	p = &a;
	return 0;
}

创建了一个名为a的int类型的整形变量,把a的地址取出来赋值给p,此时p指针存放的就是a的地址

在这里插入图片描述

用%p打印地址看到a的地址和p存放的值一样

3、解引用操作符(*)

*这个星号在不同时候的作用不一样:
在只有一个操作符时它的作用是解引用
在类型后面表示的是指针
在两个变量中间使用表示乘法

#include<stdio.h>
int main()
{
	int* p;//*表示指针
	int a = 10;
	p = &a;
	*p = 20;//*表示解引用,只有一个操作数
	a = 10 * 10;//*表示乘法
	printf("&a=%p\n", &a);
	printf("p =%p\n", p);
	return 0;
}

*为解引用时可以把指针存放地址对应的值解出来

在这里插入图片描述

可以通过指针的解引用来改变指针指向对象的值

在这里插入图片描述

4、指针的大小

在地址总线相同的情况下,所以类型的指针占用的字符大小相同
在64位下指针的字节数为8

在这里插入图片描述

在32位下指针的字节数为4,X86代表32位

在这里插入图片描述

因为指针存放的只是地址所以不同类型的指针大小也相同

三、指针变量类型的意义

1、指针类型决定了解引用的大小

因为指针大小都一样,所以指针类型的作用就没有了吗?
并不是的,类型决定了解引用时访问的字节个数
比如:
int类型是4个字节,解引用时从指针存放的地址往后读4个字节

在这里插入图片描述

char类型是1个字节,解引用时从指针存放的地址往后读1个字节

在这里插入图片描述

2、指针类型决定了指针±整数往后读的字节数

不同类型的指针在加减整数时地址跳过的字节数不同

在int类型下的指针加减
在这里插入图片描述

可以看到加减都只跳过了4个字节,因为int类型占4个字节

在char类型下的指针加减
在这里插入图片描述

可以看到跳过了1个字节,说明了指针类型存在的意义

3、void*指针

在不确定类型的指针可以用void*
void*指针又被称为泛性指针
但void*指针不能直接解引用,因为不知道要读取几个字节,通常在函数中使用void*
使用时加上强制类型转换

在这里插入图片描述

四、const修饰指针

const 是一个关键字,当它修饰的对象具有常属性

1、const修饰变量

当const修饰指针变量时,表示不能改变指针的存放的地址

#include<stdio.h>
int main()
{
	int a = 20;
	int* const p = &a;
	int b = 100;
	//p = &b;//此时不会让我们改变指针变量的指向
	*p = 100;//但可以改变指针对象的内容
	return 0;
}

const 在*星号的右边,const 修饰的是变量p,保证p的内容不变修改

2、const修饰指针变量

当const修饰指针时,指针解引用的内容不能被修改

#include<stdio.h>
int main()
{
	int a = 20;
	const int*  p = &a;
	//等价于 int const * p=&a
	int b = 100;
	p = &b;//此时我们可以改变指针变量的指向
	//*p = 100;//但不可以改变指针对象的内容
	return 0;
}

当const 在*星号左边时,const修饰的是指针解引用的内容

五、指针的运算

1、指针±整数

运行于数组中,数组中的地址是连续的,可以运用指针加减来方法其他元素

2、指针-指针

指针-指针的绝对值可以算数之间的元素个数

不存在指针+指针
就像日期加天数可以知道几天后的日期
日期-日期可以知道直接差多少天
而日期+日期没有意义

六、野指针

1、指针未初始化就使用
#include<stdio.h>
int main()
{
	int* p;
	*p =20;
	return 0;
}

这样的指针就是野指针

2、指针越界访问
#include <stdio.h>
int main()
{
 int arr[10] = {0};
*p = &arr[0];
 int i = 0;
 for(i=0; i<=11; i++)
 {
 //当指针指向的范围超出数组arr的范围时,p就是野指针 
 *(p++) = i;
 }
 return 0;
}
3、避免野指针的方法

在初始化时,把指针置NULL

#include<stdio.h>
int main()
{
	int* p =NULL;
	*p =20;
	return 0;
}

七、assert断言

在使用指针时用asser()函数断言看是否满足条件,满足条件就结束,防止后面程序崩溃
使用时引入头文件<assert.h>

#include<stdio.h>
#include<assert.h>
int main()
{
	int* p = NULL;
	assert(p != NULL);
	return 0;
}

它要求不等于NULL,如果还等于NULL就会报错

当确保程序没有问题时可以用关闭assert,让asser失效,
在程序开始加入#define NDEBUG

#define NDEBUG
#include<stdio.h>
#include<assert.h>
int main()
{
	int* p = NULL;
	assert(p != NULL);
	return 0;
}
  • 32
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值