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

news2024/11/13 14:36:27

指针变量

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

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是一种指向任意类型数据的通用指针。它可以指向任意类型的数据,但是不能通过该指针直接访问数据,需要先转换为特定的指针类型再访问

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/343540.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

线段树--RMQ问题

线段树由来算法讲解分析树的数据结构结点四个基本操作例题天才的记忆最大数由来 线段树是RMQ区间最值问题的一种解题方法&#xff0c;在给出的区间是静态不变的时候&#xff0c;可以使用ST算法进行离线查询某个区间的最值&#xff0c;先预处理后进行m次查询&#xff0c;时间复…

9. QML_OpenGL--2. 在QQuick中搭建加载OpenGL框架

1. 说明&#xff1a; OPenGL一般在 QtWidget 中使用&#xff0c;但目前使用 QML 做界面开发是一种趋势&#xff0c;同时在QML中使用OPenGL进行渲染也是十分必要&#xff0c;文章简单介绍如何在QML中使用 OPenGL&#xff0c;搭建了一种基本的框架。整体思路和在 QtWidget 中类似…

RabbitMQ学习(四):消息应答

一、消息应答的概念消费者完成一个任务可能需要一段时间&#xff0c;如果其中一个消费者处理一个长的任务并仅只完成 了部分突然它挂掉了&#xff0c;会发生什么情况。RabbitMQ 一旦向消费者传递了一条消息&#xff0c;便立即将该消 息标记为删除。在这种情况下&#xff0c;突然…

C++中引用的本质以及与指针的区别(c++数据在内存中的分配)

1、引用的意义 引用作为变量别名而存在&#xff0c;因此在一些场合可以替代指针&#xff0c;引用相对于指针来说具有更好的可读性和实用性 // swap函数的实现对比 #include <iostream> using namespace std;void swap1(int a, int b); void swap2(int *p1, int *p2); v…

【数据结构】---顺序表的实现

最近学校开始学习数据结构了&#xff0c;没事就手搓一个顺序表。&#x1f308;线性表线性表是n个具有相同特性的数据元素的有限序列&#xff0c;是一种实际中广泛使用的数据结构&#xff0c;常见的线性表有顺序表、链表、栈、队列、字符串。线性表在逻辑上是线性结构&#xff0…

【C语言学习笔记】:静态库

一、什么是库 库是写好的现有的&#xff0c;成熟的&#xff0c;可以复用的代码。现实中每个程序都要依赖很多基础的底层库&#xff0c;不可能每个人的代码都从零开始&#xff0c;因此库的存在意义非同寻常。 本质上来说库是一种可执行代码的二进制形式&#xff0c;可以被操作…

基于”PLUS模型+“生态系统服务多情景模拟预测实践技术应用

生态系统服务是人类直接或间接从生态系统中获得的惠益&#xff0c;在应对城市挑战和实施可持续发展方面发挥着至关重要的作用。随着全球城市化的快速发展, 频繁的人类活动导致了土地利用的快速变化&#xff0c;导致生态系统结构和功能的变化&#xff0c;影响生态系统服务的供应…

【Nginx】Docker配置ngnix,实现同服务器ip多站点多域名

Docker配置ngnix&#xff0c;实现同服务器ip&#xff0c;多域名映射多站点 本文首发于 慕雪的寒舍 1.说明 一般情况下&#xff0c;我们的域名映射到ip后&#xff0c;默认访问的是80端口。如果你的服务器只部署了一个服务&#xff0c;这样也是够用的。 但是很多项目对性能的占…

CAN总线详细介绍

1.1 CAN是什么&#xff1f; CAN 最终成为国际标准 &#xff08; ISO11898(高速应用)和 ISO11519&#xff08;低速应用&#xff09;&#xff09;&#xff0c;是国际上应用最广泛的现场总线之一。 1.2 CAN总线特点 多主方式: 可以多主方式工作&#xff0c;网络上任意一个节点…

前端学习第一阶段——第五章(上)

5-1 CSS基本选择器 01-CSS层叠样式表导读 02-CSS简介 03-体验CSS语法规范 04-CSS代码风格 05-CSS选择器的作用 06-标签选择器 07-类选择器 08-使用类选择器画盒子 09-类选择器特殊使用-多类名 10-id选择器 11-通配符选择器 5-2 CSS样式 12-font-family设置字体系列 13-font-s…

商场技术点-3

1.后端服务校验 1.1JSR-303介绍 JSR是Java Specification Requests的缩写&#xff0c;意思是Java 规范提案。是指向JCP(Java Community Process)提出新增一个标准化技术规范的正式请求。任何人都可以提交JSR&#xff0c;以向Java平台增添新的API和服务。JSR已成为Java界的一个…

springboot项目配置文件加密

1背景&#xff1a; springboot项目中要求不能采用明文密码&#xff0c;故采用配置文件加密. 目前采用有密码的有redis nacos rabbitmq mysql 这些配置文件 2技术 2.1 redis nacos rabbitmq 配置文件加密 采用加密方式是jasypt 加密 2.1.1 加密步骤 2.1.2 引入maven依赖 …

Android进阶之路 - StringUtils、NumberUtils 场景源码

忘记是在去年还是前年的时候遇到一个需要检测所传字符串是否为数字的场景&#xff0c;开始使用 NumberUtils.isNumber() 提示错误 &#xff0c;没有解决问题&#xff08;可能是因为依赖版本导致&#xff09;&#xff0c;最后使用的是StringUtils.isNumeric()&#xff0c;当时关…

剑指 Offer 43. 1~n 整数中 1 出现的次数

题目 输入一个整数 n &#xff0c;求1&#xff5e;n这n个整数的十进制表示中1出现的次数。 例如&#xff0c;输入12&#xff0c;1&#xff5e;12这些整数中包含1 的数字有1、10、11和12&#xff0c;1一共出现了5次。 思路 要求出小于等于 n 的非负整数中数字 1 出现的个数…

Prometheus系列(五)grafana web 配置邮件告警

目录 1. contact points&#xff08;创建告警渠道&#xff09; 2. Notification policies&#xff08;创建告警通道匹配规则&#xff09; 3. Alert rules&#xff08;配置告警策略&#xff09; 告警配置 告警页面名词解释&#xff1a; 1. contact points&#xff08;创建告…

玩转数据结构之Java实现线段树

前言 线段树是一种二叉搜索树&#xff0c;线段树的每个结点都存储了一个区间&#xff0c;也可以理解成一个线段&#xff0c;在这些线段上进行搜索操作得到你想要的答案。 线段树的适用范围很广&#xff0c;可以在线维护修改以及查询区间上的最值&#xff0c;求和。更可以扩充到…

一文浅谈sql中的 in与not in,exists与not exists的区别以及性能分析

文章目录1. 文章引言2. 查询对比2.1 in和exists2.2 not in 和not exists2.3 in 与 的区别3. 性能分析3.1 in和exists3.2 NOT IN 与NOT EXISTS4. 重要总结1. 文章引言 我们在工作的过程中&#xff0c;经常使用in&#xff0c;not in&#xff0c;exists&#xff0c;not exists来…

Unity2018.4.x~2021.3.x版 Android资源处理

注意&#xff1a;本文都是针对使用Gradle编译从Unity2018.4.x到Unity2020.3.x都是可以直接将Android的适配资源直接放到${PROJECT_PATH}/Assets/Plugins/Android/对应的目录下的&#xff0c;如&#xff1a;在此目录下可以方安卓平台对应的assets、res目录及子目录资源&#xff…

前端的CSS样式表知识提要

文章目录前言基本概念屏幕尺寸屏幕分辨率屏幕像素密度/像素密度/屏幕密度视口和浏览器窗口长度单位&#xff1a;px、em/rem和vhCSS属性的继承与覆盖CSS选择器CSS 布局基础盒子模型绝对定位和相对定位display属性浮动正常布局流&#xff08;normal flow&#xff09;Flexbox 布局…

【Python表白代码】 2.14“Valentine‘s Day”“没别的意思 就是借着特殊日子说声喜欢你”你在哪儿?我去见你~(各种玫瑰源码合集)

导语 Valentines Day Every man is a poet when he is in love 所有文章完整的素材源码都在&#x1f447;&#x1f447; 粉丝白嫖源码福利&#xff0c;请移步至CSDN社区或文末公众hao即可免费。 哈喽&#xff01;我是你们的木木子吖~ 情人节又到了&#xff0c;礼物备好了没&am…