C语言学习:初识指针(一)

本节我们要介绍的是

1.指针是什么

2.指针与指针类型

3.野指针

4.指针运算

5.指针与数组

6.二级指针

1.什么是指针

与其给出指针的定义,看完让人模糊不清,不如给出下面几个通俗易懂的要点。

 指针理解的 2 个要点:
1. 指针是内存中一个最小单元的编号,也就是地址
2. 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量
这两句话引出新的概念,什么是内存呢
内存是什么?
内存是用于暂时存储 CPU中的运算数据,以及与 硬盘等外部存储设备交换的数据。可以比作一个房间,用来存储数据的载体。
下图所示,我们把内存分成一个个小格子之后,我们给它一个个编号,这个编号就是一个地址,
那我们会想两个问题
  • 编号是如何产生的呢?
  • 我们一个内存单元该是多大呢?
编号的产生是电脑有地址线,地址线一旦通电就会产生电信号,我们把电信号转换为数字信号,那么数字信号产生的二进制序列(对电来说,只有正电与负电,也就是1或0),这个二进制序列进行编号就可以作为一个内存单元的编号了。
一个内存单元的大小最好是一个字节。
通过地址我们就可以找到一个内存单元,而且这个地址是唯一的,就像我们去酒店,通过门牌号找到我们的房间进行入住。
int main()
{
	int a = 10;
	int* p = &a;//p是指针变量,存放a的地址,类型是int*
	return 0;
}

 一个指针占几个字节,等于是一个地址的内存单元编号有多长。

32位机器上,一个字节八个bit位,32bit/8bit=4个字节,所以32位要4个字节来存储地址,64位需要8个字节存储地址,

注意,地址是不占用内存空间的,可以根据它的由来看出,它是地址线形成的,不需要专门的内存来存储这些地址,

2.指针与指针类型

指针类型的大小都是4,那指针类型有什么意义呢?

int main()
{
	int a = 0x11223344;
	int* pa = &a;
	char* pc = &a;
	printf("%p\n", pa);
	printf("%p\n", pc);
    return 0;
}

上面的代码很显然指针变量pa pc都能很好的存放a的地址,打印出来地址也都是一样的,是否说明指针类型更没有用呢?

int main()
{
	int a = 0X11223344;
	int* pa = &a;
	*pa = 0;
    return 0;
}

写入上述代码,按住F10,进入调试界面,

按下面三步走,

可以看到 ,地址a的空间确实存了我们的数据

*pa=0,说明我们把内存a的数据变成了0, 

有了上述测试的方法,我们把下面代码按照上述过程再来一把 

int main()
{
	int a = 0X11223344;
	char* pc = &a;
	*pc = 0;
    return 0;
}

 最后现象如下图所示,可以看出,只改了一个字节大小,

通过上面两次的测试,我们明白了指针类型的重要性,

存储数据时,所以类型都可以容纳,

但是一旦要解引用操作时,指针类型决定了指针进行解引用操作时,能够访问空间的大小

int*p   *p   能够访问四个字节空间

char*p  *p  能够访问1个字节空间

double*p *p 能够访问8个字节空间 

指针+-整数

写入以下代码

#include <stdio.h>
//演示实例
int main()
{
	int n = 0x11223344;
	char* pc = &n;
	int* pa = &n;

	printf("%p\n", &n);
	printf("%p\n", pc);
	printf("%p\n", pc + 1);
	printf("%p\n", pa);
	printf("%p\n", pa + 1);
	return 0;
}

运行结果如下: 

 总结:指针的类型决定了指针向前或者向后走一步有多大(距离)

具体应用可以看下面的代码(实现的效果是把数组的元素全部改为1)打开监视可以看到相应的数变化情况,而用char *p=arr则不行。

int main()
{
	int arr[10] = { 0 };
	int* p = arr;//数组名,首元素地址
	int i = 0;
	for (i = 0 ;i < 10; i++)
	{
		*(p + i) = 1;
	}
	return 0;
}

野指针

概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
哪些原因可能导致野指针呢?
1. 指针未初始化
int a;//局部变量不初始化,默认是随机值
int* p;//局部的指针变量,就被初始化为随机值
#include <stdio.h>
int main()
{ 
 int *p;//局部变量指针未初始化,默认为随机值
    *p = 20;
 return 0;
}
2. 指针越界访问
#include <stdio.h>
int main()
{
    int arr[10] = {0};
    int *p = arr;
    int i = 0;
    for(i=0; i<=11; i++)
   {
        //当指针指向的范围超出数组arr的范围时,p就是野指针
        *(p++) = i;
   }
    return 0;
}
3. 指针指向的空间释放
int* test()
{
	int a = 10;
	return &a;
}
int main()
{
	int* p = test();
	*p = 20;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值