C语言——指针

C语言——指针

1、相关概念:

  • 指针就是地址,地址就是指针
  • 指针就是内存单元的编号
  • 指针变量是存放地址(指针)的变量
  • 指针和指针变量是两个不同的概念
  • 但是要注意,通常叙述时会把指针变量简称为指针,实际他们的含义不同。
#include <stdio.h>

int main(void)
{
	int * p;//int * p不表示定义了一个名字叫做*p的变量 
			//int * p应该理解为:定义了一个只能指向(存放)int类型的地址的指针变量p。 
	int i = 3;
	int j;
	p = &i;//将 i 的地址存放 在指针变量p内 ,作用是 p 指向 i 
		/*
			1、p保存了 i 的地址,因此p指向 i 
			2、p不是i,i 也不是 p,更准确的说,修改 p 的值不影响i, 
			3、如果一个指针变量指向某个普通变量,则*指针变量就 完全等价于 普通变量 
			例子:
				如果p是个指针变量,并且p存放了普通变量i的地址,
				则p指向了普通变量 i; 
				*p完全等同于 i ;
				或者说:在所有出现*p的地方都可以写为 i ;
						在所有出现 i 的地方都可以写为 *p ; 
			
			4、*p 表示以p的内容为地址的变量, 
		*/
	j = *p; //等价于 j = i; 
	
	printf("i = %d, j = %d, *p =%d ", i, j, *p);
	return 0;
}

2、指针经典程序:

#include <stdio.h>
/*
*编写函数能够互换a , b的值
*/
//不能完成互换功能 
void  HuHuan1(int a, int b)
{
	int t;
	a = t;
	a = b;
	b = t;
 } 
 
 //不能完成互换 
void HuHuan2(int *p, int *q )
 {
 	int *t;//互换p和q的值,则t的类型应该和pq相同 
 	
 	t = q;//仅仅交换了地址,而a,b本身的值未改变 
 	q = p;
 	p = t;  
  } 
  
  //可以完成互换 
void HuHuan3(int *p, int *q )
 {				//接收a,b的是q,p而不是*q,*p。
 	int t;
 	
 	t = *q; //p是int *, *p是int 
 	*q = *p;
 	*p = t;  
  } 
  
int main(void)
{
	int a = 3;
	int b = 5;

	//HuHuan1(a, b); //执行完以后就释放了,所以互换不成功 
	//HuHuan2(&a, &b);//不能完成互换,因为该函数只是互换了qp的地址 
					//HuHuan(*a, *b);是错误写法		
	HuHuan3(&a, &b);
	printf("a = %d, b = %d\n", a, b);
					//总结: p是a的地址,*p=a;q是b的地址,*q=b,要交换的不是地址,而是地址和值!! 
	return 0;
 } 

3、数组与指针的关系

  • 指针和一维数组:

一维数组名是个指针常量,它存放的是一维数组第一个元素的地址,即:a == &a[0]

#include <stdio.h>

int main(void)
{
	int a[5];
	
	printf("%#X\n", &a[0]);//用16进制输出a[0]的地址:0X62FE00
	printf("%#X", a); //将一维数组名输出,输出:0X62FE00
	//总结:说明上面:“一维数组名”是个指针常量,它存放的是一维数组第一个元素的地址 即:a == &a[0]
	
	return 0} 
  • 程序二:
/*
	用函数输出任何数组的内容 ,需要两个参数 :数组名(首地址)和长度 
*/

#include <stdio.h>
//函数f输出任何数组的内容
 void f(int * pArr ,int len)
 {
 	int i;
 	for(i=0; i<len; i++)
 	printf("%d ", *(pArr+i));
 	printf("\n");
  } 

int main(void)
{
	int a[5] = {1,3,4,2,9};
	int b[6] = {2,5,6,3,1,9};
	int c[100] = {99,1,33}; 
	
	f(a,5); //a是int * 
	f(b,6);
	f(c,100);
	
	return 0;
 } 

4、指针的运算

  • 指针不能+,*,/
  • 如果指针变量指向的是同一块连续空间中的不同单元,则可以相减。
#include <stdio.h>

int main(void)
{
	int *p;
	int *q;
	int a[5];
	p = &a[2];
	q = &a[4];
	printf("%d", q-p);
}
  • 一个指针变量,无论它指向的变量占几个字节,该指针变量本身只占四个字节。

5、动态内存分配–malloc函数的使用

  • sizeof的使用:
#include <stdio.h>
#include <malloc.h>
int main(void)
{
	int * p = (int *)malloc(sizeof(int));//sizeof(int)返回值是int所占的字节数 
}
  • malloc函数的使用
#include <stdio.h>
#include <malloc.h>
int main(void)
{
	int i = 5;//静态分配 
	int * p = (int *)malloc(4);
	/*
		1.要使用malloc函数,必须添加<malloc.h>头文件
		2. mallco函数只有一个形参,并且形参都是整形;
		3.(4)表示请求系统为本程序分配4个字节;
		4.malloc函数只能返回第一个字节的地址; 
		5.上面的代码(第6行) 分配了8个字节,p变量占4个字节,p所指向的内存也占4个字节
		6. p本身所占的内存是静态分配的,p所指向的内存是动态分配的 
	*/
	* p = 5;//*p表示一个int变量,只是他的内存分配方式和第六行的分配方式不一样 
	free(p); //表示把p所指向的内存释放掉, p本身的内存是静态的, 不能手动释放,只能在 所在函数终止时系统释放,
			
	return 0; 
}

6、动态数组构造

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CyarJeCE-1598249039288)(D:\C语言\WorkPlace\基础知识\指针\Snipaste_2020-08-17_17-29-57.jpg)]

# 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);//本行动态构造了一个一维数组,数组名是pArr,类型是int型,其功能类似于 int pArr[len]; 
	
	//对一维数组进行操作:对动态一维数组进行赋值 
	for(i=0; i<len; i++) 
		scanf("%d", &pArr[i]);
		
	//对一维数组进行输出 
	for(i=0; i<len; i++)
	 printf("%d\n", pArr[i]);
    
    free(pArr);//释放掉动态分配的数组 
	return 0;
}

7、多级指针

# include <stdio.h> 

int main(void)
{
	int i = 10;
	int *p = &i;
	int **q = &p;
	int ***r = &q;
	//r = &p; //error 因为r存放的是int***类型,r只能存放 int**类型的地址 
	printf("i = %d", ***r); //输出i=10; 

	return 0;
}
  • 理解以下代码
#include <stdio.h>
void f(int ** q)
{
	//*q就是p 
 }
 
 void g()
 {
 	int i = 10;
 	int *p = &i; //p是int*类型,则 &p 是int**类型 
 	f(&p);
}
int main(void)
{
 	g();
 	
	 return 0;	
}
   

8、跨函数使用内存(重点)

  • 静态内存不能跨函数使用
#include <stdio.h>
void f(int ** q)//q是个指针变量,占4个字节 ,用来指向p的地址 
{
	int i = 5; 
	//*q等价于p,  
	//*p = i;erro 因为*q=i;等价于p = i;p 是一个指针变量,这样写是错的 
 	*q = &i; //
 }
 
int main(void)
{
	int *p ; 
	
 	f(&p);//p是int*类型,则 &p 是int**类型 
 	printf("%d\n", *p);//输出:5;本句语法没有问题,但是逻辑上有问题 
 						//因为函数f()中的 i 是静态变量,f()执行完之后就已经释放 
						//指针是可以一直保存 i 的地址没错,但是不应该读出i的值(i=5)但是被指针读出来了。所以这个程序是有问题的  
	return 0;	
}
   
  • 动态内存可以跨函数使用
#include <stdio.h>
#include <malloc.h> 

void f(int **q)
{
	*q = (int *)malloc(sizeof(int));//sizeof(数据类型)  返回该数据类型所占的字节数 
	//上面的代码等价于:p = (int *)malloc(sizeof(int)); 
	//q = 5; //error
   //*q = 5;//p = 5; p是指针变量,只能存放地址 
	**q = 5;//*p = 5; 
}			

int main(void)
{
	int *p;
	f(&p);
	printf("%d\n", *p); //此时这个程序在逻辑和语法上都没错 
	return 0;
 } 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值