C语言难点之指针--第一章:初识指针

什么是指针?

要讲指针这个东西,我们就得先拿一些现实之中的类似的东西来类比。

上图通过类比,说明指针与宿舍楼中的编号类似,都指向一定的空间。指针也称为地址。

初步理解指针1

我们了解了指针是什么,但是我们还是不知道指针的用途。所以,为了让指针变得有用,我们继续讲解指针的初级用法。

1.创建第一个指针变量

首先我们知道,c语言有多种数据类型,这里为了方便讲解,先创建整形指针变量。

int main() {
	int a1 = 0;
	int* p1 = &a1;//int*是一个类型,p1是变量名,合在一起就说明 p1是一个整形指针变量。
	              //&a1是取出 a1 的地址,所以这行代码的意思就是把a1的地址存放在p1里面。
	return 0;
}

也可以这样创建指针变量: 

int main() {
	int a1 = 0;
	int* p1 = NULL;//NULL的定义是0,可以用于初始化变量
	p1 = &a1;
	return 0;
}

2.第一次使用指针变量给其他变量赋值 

让我们来使用这个指针变量p1来改变它指向的变量a1的值 ,怎么通过指针变量改变指向对象的数值呢?这时候我们需要对地址进行解析——解引用操作,解引用操作符是  *  。这里我给指针变量p1前面加上 * ,对指针变量中的地址进行解引用,通过地址找到所指对象a1,然后再给a1赋值。

int main() {
	int a1 = 0;
	int* p1 = NULL;
	printf("操作前a1的数值是%d\n", a1);
	p1 = &a1;
	*p1 = 114514;
	printf("操作后a1的数值是%d\n", a1);
	return 0;
}

然而上述操作甚至不需要使用指针就能轻松实现,所以上面的代码仅供刚学指针的人参考,帮助理解指针。

初步理解指针2

上面为了帮助初学者理解指针,仅仅写了一种类型的指针——整形指针。接下来,我们要列举指针的类型了。

1.整形指针变量以及创建

                                         图中展示了创建整形指针变量的方法,其中,int *是 a 这个指针变量的类型。就是说,a是类型为int*的数据。然而,我们注意到,这个变量并没有初始化,它指向随机内存位置,十分危险。为了让这个指针变量变得安全,我们得让他指向 NULL ,以免造成不必要的麻烦。修正好的示例如下。

2.字符指针变量以及创建

创建字符指针变量和创建整形指针变量有共同点,整形指针变量是 int* 变量名,字符指针变量是 char* 变量名。示例如下:

和整形指针变量一样,我们都让他指向了NULL位置,防止造成不可预期的后果。

3.创建其他类形指针变量

上面我们只讲了 int* 类型和 char*类型的指针变量,所以我们接下来要讲其他类型的。比如,我们要创建一个长整型指针变量,我们就这样写:long* 变量名 ;创建双浮点型指针变量,可以这样写:double* 变量名 。我用图片示例:看到这里,我们已经学会了怎么创建指针变量了。

4.把其他变量的地址传给指针变量

我们刚刚只讲了怎么创建,并没有讲怎么使用,接下来我们开始把其他变量的地址传递给我们创建的指针变量。

这段代码中的占位符 %p 是用来表示地址的,a,b,c,d都是指针变量,存放他们所指向的变量的地址。运行结果如下图。由于这是X64环境,所以,地址的二进制位就有64位长度,化为16进制还有很长。接下来我切换到X86环境下再次演示一遍,地址瞬间变短了。为了方便讲解指针,我会采用X86的环境进行讲解。

我们再次运行一下程序看看地址怎么变化除了地址变化了,长度没变。

指针变量的大小

通过上面的分析,我们发现只要在同一环境下,指针变量的长度总是一样的。比如,X86下的指针变量的二进制位长度有32位,X64的指针变量的二进制位长度有64位。在计算机中,32位可以表示为32bit,64位可以表示为64bit,而8个bit等于一个字节,所以,我们发现:X86环境下的指针变量大小是4字节,X64环境下的指针变量大小是8字节。 

5.通过指针变量给指针指向变量赋值

1.  *操作符

*操作符是解引用操作符,可以理解为:解析指针变量所储存的地址,从而找到指针变量所指向的变量。接下来使用printf函数演示 *指针变量 。*指针变量 可以找到指针变量所指向的变量,既然这样,我们可以通过它来改变变量的数值。

2.通过 *指针变量 改变所指向变量的数值

成功通过指针变量修改所指向变量的值。这时候,我们发现,这东西还不如直接 变量名 = 数值; 的确,但是指针变量还有别的玩法。

3.通过指针变量修改const修饰的变量

上图中,我对两个变量的不同位置都加上了const进行修饰,使得上面两个变量都变成了常变量,这导致我们不能通过变量名 = 数值; 的方法给变量赋值了。但是,我们可以利用指针变量来修改这也报错啊,但是没关系,修改一下就能用因为这里的 &a和&b 拿到的地址类型是const int* 的,所以编译器报错,然而使用强制类型转换转换就能解决这个问题。抽象的来了,通过监视窗口我们可以看到,我们已经成功改变了a和b的数值,然而,编译器告诉我们,我没改变,这个是很抽象的。你猜猜为什么会这样,其实这是编译器的问题,但凡我们换一个编译器,结果就是这样的:

由此看出,这段代码在不同编译器中的结果不一致。

 初步理解指针3

1.const修饰的指针变量

众所周知,const修饰的变量是常变量,不能通过一般手段修改。如果用const修饰指针变量呢?注意:const修饰指针变量有两种情况,第一种是这样的可以发现这个两种写法出来的数据类型都是 const int*类型 ,所以这两中写法等价。还有一种写法,如下图所示:这个a的数据类型是 int* const

2.两种 const修饰指针变量 的区别

我们注意到它们的类型不同,一种是 const int*,另一种 是int* const。其中 const int* 类型的变量不能通过解引用的方式操作所指向的对象,但是能通过解引用找到所指对象,而且可以改变他的所指对象,下面我用截图说明这点另一种类型int *const 可以通过解引用找到所指对象,且可以通过解引用的方式操作所指对象,但是不能改变他的所指对象 我照样用图片说明:看到这,我们可以对const修饰指针变量给出一个结论:

结论:const在指针变量的*的左边的时候,这个指针变量的类型是 const 数据类型* ,不能通过解引用的方式操作所指向的对象,但是能通过解引用找到所指对象,而且可以改变他的所指对象。const在指针变量的*的左边的时候,这个指针变量的类型是         数据类型* const 可以通过解引用找到所指对象,且可以通过解引用的方式操作所指对象,但是不能改变他的所指对象

进阶理解指针0

上面的东西一般情况下都能很容易看懂,接下来得上点难度了。

1.一维数组指针

数组指针是一个指针,就是数组的地址,例如,我们创建一个数组并取出数组的地址存放地一个数组指针变量里:

1.一维数组指针的数据类型

上面的代码中,我们创建了一个长度为10的整形数组,这个数组指针的类型是 int(*)[10],为了存放这个数组的地址,我们要创建一个int (*)[10]类型的指针变量。上图我创建的指针变量是           int (*parr1)[10]。讲到这里,你可能要问我了,为什么不是int *parr1[10]呢?问的不错,因为这样写,创建的是一个整形指针数组,里面存放int*类型的数据。这是等会我要讲的。

2.通过指针操纵数组 

有心的小伙伴已经在模仿上述代码时候发现了,我创建的数组arr1里面放的数据的地址都是int*类型的,而且,我们已经知道了怎么使用解引用操作符的使用。所以,接下来,我们通过循环结构和指针给arr1初始化。

这下问题来了,parr1前面的两个*是什么东西?我给你解释一下。

 看到这里,是否感觉难度在一路飙升?不要放松,下一篇博客讲开始讲点比这更难的!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值