C语言学习笔记(七): 指针的使用

指针变量

指针是一种特殊的变量,它存储的是某个变量的内存地址。指针变量可以存储内存地址,并且通过指针变量可以间接操作内存中的数据

include <stdio.h>
int main()
{
	int a=1, * p;       //定义指针变量,*是指针运算符
	p = &a;				//把a的地址赋给指针变量p,&是取地址运算符														
	printf("%d\n", *p);	//以整数形式输出指针变量p所指向的变量的值,即a的值							
	*p = 2;				//将整数1赋给p当前所指向的变量,由于p指向变量a,相当于把1赋给a,即a=2	
	printf("a=%d,a的地址是%d",a,p);		//以十进制形式输出指针变量p的值,即输出变量a的地址;a的值变为了2
}

通过指针引用数组

数组元素的指针

一个变量有地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。指针变量既然可以指向变量,当然也可以指向数组元素。

若指针变量直接指向数组变量名,则表示指向数组第一个元素的地址。

int a[10]={1,3,5,7,9,11,13,15,17,19};	//定义a为包含10个整型数据的数组	
int *p = &a[0];		//定义一个整型指针变量,并指向整型数组	
int a[10]={1,3,5,7,9,11,13,15,17,19};		
int *p = a;		//等价于int *p = &a[0];	

数组元素里指针的运算

在指针已指向一个数组元素时,指针可以进行以下运算:

  • p+1:表示指向同一数组的下个元素
  • p-1:表示指向同一数组的上个元素
  • p++,p–:指针的自加自减运算

若p的初值是a(即&a[0]),则p+i和a+i就是数组元素a[i]的地址,它俩指向a[i]

*(p+i)或*(a+i)是p+i或a+i指向的数组元素值,即a[i]

include <stdio.h>
int main()
{
	int a[10] = { 0,1,2,3,4,5,6,7,8,9 };
	int *p = a;

	//下述三个输出结果均为2
	printf("%d", *(p + 2));
	printf("%d", *(a + 2));
	printf("%d", a[2]);
}

通过数组名作函数参数

变量名数组名作为函数参数的比较

image-20220309215549405

int main()
{	void fun(int arr[], int n);	//对fun函数的声明
	int array[10];			//定义array数组fun(array,10); 			//array是实参,arr是形参,
	return 0;
} 

void fun (arr[ ],int n)   
{	printf(%d\n″, *arr);		//输出array[0]的值
	arr=arr+3;			//形参数组名可以被赋值
	printf(%d\n″, *arr);		//输出array[3]的值
}

image-20211219210339704


通过指针引用字符串

字符串的引用方式

/*通过定义字符串数组*/
include <stdio.h>
int main()
{	char string[]="I love China!";	//定义字符数组string
	printf("%s\n",string);		//用%s格式声明输出string,可以输出整个字符串
	printf("%c\n",string[7]);		//用%c格式输出一个字符数组元素,输出'C'
	return 0;
}

字符串指针作函数参数

将字符串指针作为函数参数, 有以下四种传递方式

实参形参
字符数组名字符数组名
字符数组名字符指针变量
字符指针变量字符指针变量
字符指针变量字符数组名

下述代码用于实现字符串拷贝

include <stdio.h>
int main()
{	void copy_string(char from[], char to[]);	//函数声明
	char a[]="I am a teacher.";		//定义字符数组a并初始化
	char b[]="You are a student.";	//定义字符数组b并初始化
	char *from=a,*to=b;	//from指向a数组首元素,to指向b数组首元素 
	printf("string a=%s\nstring b=%s\n",a,b);
	printf("copy string a to string b:\n");
	copy_string(from,to);	//实参为字符指针变量
	printf("\nstring a=%s\nstring b=%s\n",a,b);
	return 0;
}

void copy_string(char from[], char to[]) 		//形参为字符数组
{	int i=0;
	while(from[i]!='\0')
	{	to[i]=from[i]; i++;}
	to[i]='\0';
}

指向函数的指针

什么是函数的指针

函数名就是函数的指针,它代表函数的起始地址。


函数指针变量调用函数

/*判断两数的大小*/
include <stdio.h>
int main()
{	int max(int,int);	//函数声明
	int (*p)(int,int);	//定义指向函数的指针变量p,表示指向函数类型为整型且有两个整型参数的函数
	int a,b,c;
	p=max;			//使p指向max函数
	printf("please enter a and b:");
	scanf("%d,%d",&a,&b);
	c=(*p)(a,b);		//通过指针变量调用max函数
	printf("a=%d\nb=%d\nmax=%d\n",a,b,c);
	return 0;
}
int max(int x,int y)		//定义max函数
{	int z;
	if(x>y)z=x;
	else z=y;
	return(z);
}

指针数组

什么是指针数组

一个数组,若其元素均为指针类型数据,称为指针数组,也就是说,指针数组中的每一个元素都存放一个地址,相当于一个指针变量。

如下代码定义了一个指针数组, 用于存放int类型的指针元素

int *p[4]; 

使用实例

include <stdio.h>
int main()
{
	int a[5] = { 1,3,5,7,9 };
	int* num[5] = { &a[0],&a[1],&a[2],&a[3],&a[4] };
	int** p, i;				//p是指向指针型数据的指针变量
	p = num;				//使p指向num[0],即p指向&a[0]
	for (i = 0; i < 5; i++)
	{
		printf("%d ", **p);  //*p=&a[0]  **p=a[0]
		p++;
	}
	printf("\n");
	return 0;
}

动态内存分配

定义

全局变量是分配在内存中的静态存储区的,非静态的局部变量(包括形参)是分配在内存中的动态存储区的

除此以外,C语言还允许建立内存动态分配区域,以存放一些临时用的数据,这些数据不必在程序的声明部分定义,也不必等到函数结束时才释放,而是需要时随时开辟,不需要时随时释放。这些数据是临时存放在一个特别的自由存储区,称为(heap)。可以根据需要,向系统申请所需大小的空间。

由于未在声明部分定义它们为变量或数组,因此不能通过变量名或数组名去引用这些数据,只能通过指针来引用


动态分配内存的函数

malloc函数

该函数是一个指针型函数,返回的指针指向该分配域的第一个字节

/* void *malloc(unsigned int size); */

int *p = malloc(100);   //开辟100字节的临时分配域,函数值为其第1个字节的地址;若函数执行失败(如内存空间不足),则返回空指针(NULL)

calloc函数

在内存的动态存储区中分配n个长度为size的连续空间,这个空间一般比较大,足以保存一个数组。

/* void *calloc(unsigned n,unsigned size); */

p=calloc(50,4);		//开辟50×4个字节的临时分配域,把首地址赋给指针变量p;若执行失败返回NULL

realloc函数

如果已经通过malloc函数或calloc函数获得了动态空间,想改变其大小,可以用realloc函数重新分配。

/* void *realloc(void *p,unsigned int size) */
realloc(p,50);	//将p所指向的已分配的动态空间改为50字节;失败则返回NULL

free函数

是释放指针变量p所指向的动态空间,使这部分空间能重新被其他变量使用。p应是最近一次调用calloc或malloc函数时得到的函数返回值

free(p); //释放指针变量p所指向的已分配的动态空间,无返回值

使用实例

建立动态数组,输入5个学生的成绩,另外用一个函放数检查其中有无低于60分的,输出不合格的成绩

include <stdio.h>
include <stdlib.h>				//程序中用了malloc函数,应包含stdlib.h
int main()
{
	void check(int*);				//函数声明
	int* p1, i;						//p1是int型指针
	p1 = (int*)malloc(5 * sizeof(int));	//开辟动态内存区,(int *)表示强制指针类型转换
	for (i = 0; i < 5; i++)
		scanf("%d", p1 + i);			//输入5个学生的成绩 
	check(p1);					//调用check函数
	return 0;
}

void check(int* p)					//定义check函数,形参是int*指针
{
	printf("They are fail:");
	for (int i = 0; i < 5; i++)
		if (p[i] < 60) printf("%d \0", p[i]); 	//输出不合格的成绩 
	
}

指针总结

变量定义含义
int i定义整型变量i
int *p定义p为指向整型数据的指针变量
int a[5]定义整型数组a,它有5个元素
int *p[4]定义指针数组p,它由4个指向整型数据的指针元素组成
int (*p)[4]p为指向包含4个元素的一维数组的指针变量
int *p()p为返回一个指针的函数,该指针指向整型数据
int (*p)()p为指向一个返回值为整数的函数的指针
int **pp是一个指针变量,它指向一个指向整型数据的指针变量
void *pp是一种指向任意类型数据的通用指针。它可以指向任意类型的数据,但是不能通过该指针直接访问数据,需要先转换为特定的指针类型再访问
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值