C语言X天学习计划——灵魂~指针

指针就是内存地址,使用指针访问变量,就是直接对内存中的数据进行操作。

1.指针的简单用法

  • 初识指针
/*
	2021年1月24日13:14:41
	初识指针
*/

# include <stdio.h>

int main(void)
{
	int * p;	// p是变量的名字, int * 表示 p 变量存放的是int类型变量的地址
	int i = 3;

	p = &i;		// 1.p保存了i的地址,p-->i;		2.p 、i 的值互不影响	

	if (* p == i)		
	{
		printf("*p 和 i 的值相等:");
		printf("i = %d\n", * p);	   //  3.如果一个指针变量指向了某个普通变量则 *指针变量 就等同于普通变量 * p == i
	}

	else 
		printf("* p != i\n");

	return 0;
}

/*
----------------------------------------------
在VC++6.0中运行的结果为:
*p 和 i 的值相等:i = 3

思考: p = &i;		*p = i;
	  * & 相当于逆运算
	  *p 是以p的内容为地址的变量
----------------------------------------------
*/
/*
	2021年1月26日10:51:13
	初识指针
	《C语言从入门到精通》
*/
# include <stdio.h>

int main(void)
{
	int i, * p;
	char m, * q;

	i = 6;
	m = 'A';

	p = &i;
	q = &m;

	printf("i = %d, i的地址为:%d\n", i, &i);
	printf("p = %d, *p = %d, p的地址为:%d\n", p, *p, &p);
	printf("m = %c, m的地址为:%d\n", m, &m);
	printf("q = %d, *q = %d, q的地址为:%d\n", q, *q, &q);

	return 0;
}

/*
-------------------------------------------------------------
在VC++6.0中运行结果为:
i = 6, i的地址为:1703724
p = 1703724, *p = 6, p的地址为:1703720
m = A, m的地址为:1703716
q = 1703716, *q = 65, q的地址为:1703712

结论:1.每个变量都有不同的地址
	  2.p表示i的地址			 p = &i;
	  3.p指向i
	  4.*p访问变量i的值		*p = i;
-------------------------------------------------------------
*/

2.指针的重要性

  • 1.表示复杂的数据结构
  • 2.快速传递数据
  • 3.使函数返回多个值
  • 4.直接访问硬件
  • 5.处理字符串
  • 6.理解面向对象的基础

3.指针的定义

1.地址

  • 内存的单元编号
  • 从零开始的非负整数

2.指针

  • 指针就是地址
  • 指针变量就是存放内存单元编号的变量

4.指针的分类

1.基本类型指针

  • 程序一:交换两个数的值
/*
	2021年1月26日11:35:37
	交换两个数的值
*/
# include <stdio.h>

int main(void)
{
	int i, j;
	int * p, * q, * m;

	p = &i;
	q = &j;

	printf("请输入变量i 和 变量j: \n");
	scanf("%d %d", &i, &j);

	if (*p < *q)
	{
		m = p;		// 源代码必须写为:m = p; 目的是:交换p q存储单元的值
		p = q;
		q = m;		/* 不能写为 * m = * p; 原因是:* m 仅仅声明了 
					但没有初始化 没有明确的指向 他可能指向一个不存在的存储区域 
					变量 i 存储在一个不存在的区域内 当然会报错 */
	}

	printf("i的值为%d i的地址值为:%d *p = %d\n", i, &i, *p);
	printf("j的值为%d j的地址值为:%d *q = %d\n", j, &j, *q);

	return 0;
}

/*
-----------------------------------------------------------
在VC++6.0中运行的结果为:
请输入变量i 和 变量j:
2 3
i的值为2 p的值为:1703724 *p = 3
j的值为3 q的值为:1703720 *q = 2
-----------------------------------------------------------
*/
  • 常见错误1
    指针需要初始化 否则指针默认空指针 没有p = &i; p无法指向i
# include <stdio.h>

int main(void)
{
	int i = 8;
	int * p;

	* p = i;	// *p 与 i 的地址不同, *p 仅与 i 在数值上相同,需要初始化
	printf("%d\n", * p);

	return 0;
}
  • 常见错误2
# include <stdio.h>

int main(void)
{
	int i = 8;
	int * p;
	int * q;

	p = &i;
	// *q = p;  error 类型不同
	// *q = *p;	error q没有分配地址空间		
	// p = q;	error q 是未知变量 赋值给 p p 也将变为垃圾值 *q 当然也无法输出(内存空间未分配)
	q = p;		// 正确 p 是 i 的地址 q 是地址变量 即 q 也为 i 的地址(q---> i) 所以 *q 为 i 
	printf("%d\n", *q);
	
	q = &(*p);	// 正确 q---> i
	printf("i = %d\n", *q);

	return 0;
}

/*
-------------------------------------------
在VC++6.0中运行结果为:
8
i = 8
-------------------------------------------
*/
  • 指针交换两个数的值
/*
	2021年1月24日18:15:36
	指针交换两个数的值

	目的:1.自定义函数与主函数通过指针联系起来。
		  2.主函数的实参只能单向调用自定义函数的形参。
		  3.指针可以使主调函数返回多个值 不用指针两个数不能交换,
		  函数调用结束后实参的值任然不变。
*/
# include <stdio.h>

void swap(int * p, int * q)
{		
	int t;
	
	t = * p;	// *p *q 为值  
	* p = * q;		
	* q = t;

}

int main(void)
{
	int a = 5;
	int b = 2;

	swap(&a, &b);	// p = &a
	printf("a = %d b = %d\n", a, b);

	return 0;
}

/*
----------------------------------------
在VC++6.0中运行结果为:
a = 2 b = 5
----------------------------------------
*/

*的含义
1.乘法
2.定义指针变量 int * p;
3.指针运算符 * p = i;

2.指针和数组

1.指针和一维数组

  • 数组名

  1. 一维数组名是个指针常量 例:a = &a[0] (×) a是一个常量
  2. 他存放的是一维数组第一个元素的地址 例:a == &a[0] (√)

  • 下标和指针的关系
  1. 如果p是个指针变量,则 p[i] == *(p+i)
  • 指针变量的运算(地址的运算)
  1. 移动指针:通过加减一个整数,实现对指针位置的移动

  • 假如数据类型为整型:4字节
P-1 地址为 1030
P 地址为 1034
P+1 地址为 1038
/*
	2021年1月26日16:06:37
	指针的运算①
*/

# include <stdio.h>

int main(void)
{
	int a = 2;
	int b = 5;
	int * p, * q;

	p = &a;
	q = &b;

	printf("p的值为:%d p的地址为:%d\n", *p, p);
	printf("q的值为:%d q的地址为:%d\n", *q, q);
	printf("p-1的地址为:%d\n", *(p-1));			// *(p-1) p指向的地址减一个存储单元即后移4字节的地址存储的数据
	printf("p的地址-1后的值为:%d\n", *p-1);		// *p-1 p指向的存储单元的值减一 

	return 0;
}

/*
---------------------------------------------------------------------------------------------------------------
在VC++6.0中运行结果为:
p的值为:2 p的地址为:1703724
q的值为:5 q的地址为:1703720
p-1的地址为:5
p的地址-1后的值为:1

结论:*(p-1) 和 b 的值相同
原因:a、b占用连续的存储单元 *(p-1)就相当于p的地址后移4字节的地址存储的数据即为b的值 所以*(p-1) ==  b。
---------------------------------------------------------------------------------------------------------------
*/

  1. 两指针相减
  2. 两指针比较
  3. sizerof(数据类型or 变量名) 功能:返回该数据所占的字节数
  4. 一个指针变量 无论指向什么数据类型 都占用四字节 因为输出占用32根线 每一根线表示一位 有0 1 两种状态 一字节又是八位 所以占用四字节。

2.指针和二维数组

一、动态内存分配

  • 1.数组长度必须事先制定,且只能是整数,不能是变量
  • 2.传统的数组 分配的内存空间程序员不能手动释放,数组一旦定义,存储空间就被分配了,直到函数运行结束,空间被释放。
  • 3.数组的长度不能在函数运行过程中扩缩。
  • 4.函数内部的传统数组相当于局部变量 使用完后空间被自动释放,不能供其他函数使用

二、动态存储的意义

  • 1.静态数组有很多缺陷,动态数组完美解决。

三、动态内存分配实例

  • 程序一:malloc 函数的简单介绍
/*
	2021年1月24日19:27:28
	malloc 函数的简单介绍
*/
# include <stdio.h>
# include <malloc.h>	// 头文件必须存在

int main(void)
{
	int i= 5;	// 静态分配4字节
	int * p = (int *)malloc(4);		/* 1.包含头文件
								     					   					   2.malloc只有一个形参 且必须为整型
																				3.malloc(4) 请求系统分配4字节
										4.只能返回第一个字节的地址
										5.强制类型转换目的是为了说明数据类型
															 	   	 		 	6.malloc函数都为动态存储
										7.p本身所占的内存是静态分配的 p指向的是动态存储
																				8.int * p = (int *)malloc(4);	分配了八字节 变量占4字节 p指向的地址占4字节
									*/
	*p = 5;		   	// 数据相同 但动态分配
	printf("HH\n");
	printf("i = %d *p = %d\n", i, *p);
	free(p);	     // free(p)表示把p所指向的内存给释放掉
	printf("i = %d *p = %d\n", i, *p);	// *p 错误:空间已经被释放 *p 无法指向任何数据 在其他编译器中会报错

   	return 0;
}

/*
--------------------------------------------
在VC++6.0中运行的结果为:
HH
i = 5 *p = 5
i = 5 *p = -572662307

结论:*p = -572662307 垃圾值 因为空间被释放
--------------------------------------------
*/
  • 程序二:malloc 的函数用法
/*
	2021年1月27日14:06:25
	malloc 的函数用法
*/
# include <stdio.h>
# include <malloc.h>

void f(int * p)
{
	*p = 2;
}
int main(void)
{
	int * p = (int *) malloc(sizeof(int));
	*p = 10;

	printf("%d\n", *p);
	f(p);
	printf("%d\n", *p);

	return 0;
}

/*
------------------------------------------
在VC++6.0中运行的结果为:
10
2
------------------------------------------
*/

程序三、动态一维数组实例

/*
	2021年1月27日15:12:53
	动态一维数组实例
*/

# include <stdio.h>
# include <malloc.h>

int main(void)
{
	int a[5];	
	int len;
	int * pArr;
	int i;

	// 动态构造一维数组
	printf("请输入要存放的元素的个数:");
	scanf("%d", &len);
	pArr = (int *)malloc(4 * len);	// 动态构造了一个数组 类似 int pArr[len];
	
	// 对一维数组进行赋值
	printf("对数组进行赋值:");
	for (i=0; i<len; i++)
		scanf("%d", &pArr[i]);

	// 对一维数组进行输出
	printf("一维数组的内容是:\n");
	for (i=0; i<len; i++)
		printf("pArr[%d] = %d\n", i, pArr[i]);

	return 0;
}

/*
----------------------------------------------------------
在VC++6.0中运行结果为:
请输入要存放的元素的个数:5
对数组进行赋值:88 55 66 99 44
一维数组的内容是:
pArr[0] = 88
pArr[1] = 55
pArr[2] = 66
pArr[3] = 99
pArr[4] = 44
----------------------------------------------------------
*/

3.指针和函数

4.指针和结构体

5.多级指针

多级指针目的是为了跨函数使用

/*
	2021/1/30-21点25分	
	初识多级指针
*/

# include <stdio.h>

int main(void)
{
	int i = 10;
	int * p = &i;
	int ** q = &p;
	int *** m = &q;		// m = &q; m 为 int *** 类型 只能存放 int ** 类型变量的地址

	printf("i = %d\n", *** m);	// VC6.0中运行结果为:i = 10

	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

想前

看客 多少意思意思

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

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

打赏作者

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

抵扣说明:

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

余额充值