C语言指针入门详解

news2024/11/15 21:53:20

一、指针简介

  • 指针(Pointer)是C语言的一个重要知识点,其使用灵活、功能强大,是C语言的灵魂
  • 指针与底层硬件联系紧密,使用指针可操作数据的地址,实现数据的间接访问
  • 指针就是地址,通过访问此地址来获取该地址存储的数据

二、计算机存储机制

每个字节(Byte)(8位Bits)对应有自己的地址;

1、 int a = 0x123456;(一个整型是4个字节,即32位),下图中是以小端字节序跨字节存储,有关字节序内容请参考Linux系统编程-网络通信_linux系统网络通信_单行梦想家的博客-CSDN博客

2、short b = 0x5A6B;

3、char c[ ] = {0x33,0x34,0x35};  char型是一个字节;数组在内存中必须分配一个连续的线性空间;

如果要把short  d[ ] = {0x5A6B,0X5B6A}存储,表示为图二,数组元素按顺序存储(0->1...),每个short按小端字节序存储

图一
图二

 

 

 

 

 

三、定义指针

  • 指针即指针变量,用于存放其他数据单元(变量/数组/结构体/函数等)的首地址
  • 若指针存放了某个数据单元的首地址,则这个指针指向了这个数据单元
  • 若指针存放的值是0,则这个指针为空指针
  • 定义一个指针变量: 

16位系统:x=2,32位系统:x=4,64位系统:x=8  (与系统位宽相等) 

demo1:查看数据类型的长度(即存储大小)

#include <stdio.h>

int main()
{
	int a;
	int *p1;
	
	char b;
	char *p2;
	
	printf("a:%d\n",sizeof(a));
	printf("p1:%d\n",sizeof(p1));
	printf("b:%d\n",sizeof(b));
	printf("p2:%d\n",sizeof(p2));
	
	return 0;
	
}

>>>运行结果:
a:4
p1:8
b:1
p2:8

四、指针操作

若已定义:     

int a;        //定义一个int型的数据     

int *p;        //定义一个指向int型数据的指针

则对指针p有如下操作方式:

 

demo2:打印char型变量a的地址

#include <stdio.h>

int main()
{
	char a = 0x66;
	char *p = &a;
	
	printf("a:%x\n",a);
	printf("p:%x\n",p);
    printf("取内容p:%x\n",*p);
	
	return 0;
	
}

>>>运行结果:
a:66
p:61fe17
取内容p:66

 指针++的操作:偏移的是1个数据宽度,int*就是4个字节,char*就是1个字节,short*2个字节

demo3:指针++操作

#include <stdio.h>

int main()
{
	char a;
	char *p1 = &a;
	
	int b;
	int *p2 = &b;
	printf("p1:%x\n",p1);
	printf("p2:%x\n",p2);
	
	p1++;
	p2++;
	printf("p1++:%x\n",p1);
	printf("p2++:%x\n",p2);
	
	return 0;
	
}

>>>运算结果:
p1:61fe0f
p2:61fe08
p1++:61fe10
p2++:61fe0c

五、数组与指针

  • 数组是一些相同数据类型的变量组成的集合,其数组名即为指向该数据类型的指针。
  • 数组的定义等效于申请内存、定义指针和初始化

例如:   

char c[ ] = {0x33, 0x34, 0x35};

等效于:    申请内存         

                  定义 char *c = 0x4000;  

                  初始化数组数据 

利用下标引用数组数据也等效于指针取内容

例如:    c[0];    等效于:    *c;         

               c[1];    等效于:    *(c+1);         

               c[2];    等效于:    *(c+2); 

demo4:数组与指针

#include <stdio.h>
#include <stdlib.h>

int main()
{
	//char a[] = {0x33,0x34,0x35};//等效于以下步骤
	char *a;
	a=malloc(3*1);
	*a=0x33;
	*(a+1)=0x34;
	*(a+2)=0x35;
	
	printf("a[0]=%x\n",a[0]);
	printf("a[1]=%x\n",a[1]);
	printf("a[2]=%x\n",a[2]);
	
	printf("a[0]=%x\n",*a);
	printf("a[1]=%x\n",*(a+1));
	printf("a[2]=%x\n",*(a+2));
	
	return 0;
	
}

>>>运算结果:
a[0]=33
a[1]=34
a[2]=35
a[0]=33
a[1]=34
a[2]=35

 六、注意事项

  • 在对指针取内容之前,一定要确保指针指在了合法的位置,否则将会导致程序出现不可预知的错误
  • 同级指针之间才能相互赋值,跨级赋值将会导致编译器报错或警告

 七、指针应用

传递参数

  • 使用指针传递大容量的参数,主函数和子函数使用的是同一套数据,避免了参数传递过程中的数据复制,提高了运行效率,减少了内存占用
  • 使用指针传递输出参数,利用主函数和子函数使用同一套数据的特性,实现数据的返回,可实现多返回值函数的设计

传递返回值

  • 将模块内的公有部分返回,让主函数持有模块的“句柄”,便于程序对指定对象的操作

直接访问物理地址下的数据

  • 访问硬件指定内存下的数据,如设备ID号等
  • 将复杂格式的数据转换为字节,方便通信与存储
demo5:函数返回多个返回值,求数组中最大值以及该值出现的次数

#include <stdio.h>

void FindMaxAndCount(int *max,int *count,const int *array,int length)
{
	int i;
	*max=array[0];
	*count=1;
	
	for(i=1;i<length;i++)
	{
		if(array[i]>*max)
		{
			*max=array[i];
			*count=1;
		}
		else if(array[i]==*max)
		{
			(*count)++;
		}
	}
} 

int main()
{
	int a[]={1,2,4,6,4,6,3};
	int Max;
	int Count;
	
	FindMaxAndCount(&Max,&Count,a,7);
	
	printf("Max=%d\n",Max);
	printf("Count=%d\n",Count);
	
	return 0;
	
}

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

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

相关文章

AIGC人工智能涉及三十六职业,看看有没有你的职业(一)

文章目录 一只弹吉他的熊猫 神奇的企鹅 功夫熊猫 视觉光影下的女子 闪光灯效 局部柔光 生物光 LOGO设计 制作儿童绘本故事 换脸艺术 打造专属动漫头像 包装设计之美 建筑设计 如何转高清图 生成3D质感图标 生成微信表情包 探索美食摄影的奇妙之旅 蛋糕创意设…

docker-compose管理创建LNMP服务并运行Wordpress网站平台

文章目录 一&#xff0e;项目环境1. 环境描述2.项目需求 二&#xff0e;部署过程1.安装Docker2.安装Docker加速器3.Docker-Compose安装部署4.准备依赖文件、配置nginx5.配置mysql6.配置php7.编写docker-compose.yml8.验证 三.容器快照&#xff0c;然后将Docker镜像打包成tar包备…

Wireshark流量分析

目录 1.基本介绍 2.基本使用 1&#xff09;数据包筛选: 2&#xff09;筛选ip&#xff1a; 3&#xff09;数据包还原 4&#xff09;数据提取 3.wireshark实例 1.基本介绍 在CTF比赛中&#xff0c;对于流量包的分析取证是一种十分重要的题型。通常这类题目都是会提供一个包含…

Config:服务端连接Git配置

创建子模块 Pom文件 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org…

<C++> 内存管理

1.C/C内存分布 让我们先来看看下面这段代码 int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] {1, 2, 3, 4};char char2[] "abcd";char *pChar3 "abcd";int *ptr1 (int *) mal…

Spring Cloud 2022.x版本使用gateway和nacos实现动态路由和负载均衡

文章目录 1、nacos下载安装1.1、启动服务器1.2、关闭服务器1.3、服务注册&发现和配置管理接口 2、代码示例2.1、app1工程代码2.2、app2工程代码2.3、gateway网关工程代码 3、动态配置网关路由3.1、配置动态路由3.2、配置为负载模式 4、gateway配置规则4.1、请求转发&#x…

PADS layout 使用记录-封装name

1. 元件封装添加位号等标签 pads layout中封装的name不见了&#xff0c;好久不知道怎么添加回来&#xff0c;终于找到了“添加新标签” 按钮&#xff1a; 点击之后&#xff0c;在这里直接设置就好了

RK3588开发板编译环境Ubuntu20.04编译配置增加交换内存

迅为提供的编译环境 Ubuntu20.04 默认配置了交换内存是 9G&#xff0c;如果在编译过程中&#xff0c;因内 存不够而编译报错&#xff0c;可以参考本小节进行设置。 这里举例分配 5G 交换内存。 在开始之前&#xff0c;使用命令检查一下您的 ubuntu 的 swap 分区。 sudo swa…

DataFun:推荐系统峰会

工程架构与训练推理 TFDE 多场景多目标融合 企业知识推荐系统 ATA内部社区 房产推荐场景的算法实践

智驾算力芯片市场仍处于「波动」周期,Momenta曝光自研NPU

用「冷热不均」来形容当下的汽车芯片赛道&#xff0c;再合适不过了。 本周&#xff0c;英伟达公布的第二财季&#xff08;5-7月&#xff09;营收达到创纪录的135亿美元&#xff0c;大幅超出了此前市场普遍预期的略高于110亿美元&#xff0c;同比增速更是达到了101%。 其中&…

AIGC人工智能涉及三十六职业,看看有没有你的职业(二)

文章目录 如何生成IP盲盒 设计儿童节海报 制作商用矢量插画 设计徽章 图片融合 后缀参数 Stylize 风格化 赛博朋克头像 中国风瓷娃娃 生成线稿 制作时尚音乐唱片封面 T恤图案设计-告白气球 引领时尚潮流的服装设计之旅 独一无二的包包奇迹 手机壳设计探险 如何生…

c#写的端口监听,程序退出后,再次运行提示端口占用,且进程不存在

我用c#写了一个监听29999端口,进程结束后再次启动发现端口被占用&#xff0c;但是运行netstat -ano | findstr 29999找到进程ID后&#xff0c;却没有这个进程 经查询这个监听29999进程虽然没了&#xff0c;但是要找到他的父进程&#xff0c;把父进程关闭了才可以&#xff0c;参…

骨传导耳机值得入手吗?盘点最值得入手的几款骨传导耳机

无线耳机最近一两年越来越受欢迎&#xff0c;市场上不同形态的耳机品类让人眼花缭乱&#xff0c;从骨传导&#xff0c;夹耳式到气传导等等都有&#xff0c;尤其是不用入耳佩戴的耳机&#xff0c;不伤耳朵&#xff0c;佩戴更舒适更安全&#xff0c;而骨传导耳机可以说是近几年来…

c++中i++和++i的区别

结论 1. i 是两步操作&#xff0c;第一步&#xff1a;a i 第二步&#xff1a;i i1&#xff0c;最终返回a&#xff0c;但a是不具名的&#xff0c;也无法取地址 2. i 也是两步操作&#xff0c;第一步&#xff1a;i i1 第二步&#xff1a;return i&#xff0c;最终返回…

pywebview 通过 JSBridge 调用 TTS

pip install pywin32 ; pip install pywebview ; 通过 JSBridge 调用本机 TTS pip install cefpython3 cefpython3-66.1-py2.py3-none-win_amd64.whl (69.0 MB) Successfully installed cefpython3-66.1 编写 pywebview_tts.py 如下 # -*- coding: utf-8 -*- ""&…

vscode | 开发神器vscode自定义用户代码片段

目录 一、增加二、删除三、语法四、变量 一、增加 点击&#xff1a;左下角设置齿轮按钮——>用户代码片段 点击&#xff1a;新建全局代码片段文件 输入文件名 会出现如下界面 配置以下语句 "cls": {"scope": "javascript,typescript",…

(学习笔记-调度算法)磁盘调度算法

磁盘结构&#xff1a; 常见的机械磁盘是上图左边的样子&#xff0c;中间圆的部分是磁盘的盘片&#xff0c;一般会有多个盘片&#xff0c;每个盘面都有自己的磁头。右边的图就是一个盘片的结构&#xff0c;盘片中的每一层分为多个磁道&#xff0c;每个磁道分为多个扇区&#xff…

C++:命名空间,缺省参数,函数重载,引用,内联函数

个人主页 &#xff1a; 个人主页 个人专栏 &#xff1a; 《数据结构》 《C语言》《C》 文章目录 前言一、命名空间命名空间的定义命名空间的使用 二、缺省参数缺省参数概念缺省参数分类 三、函数重载函数重载的概念 四、引用引用的概念引用特性引用的使用场景引用与指针的区别 …

【中危】Spring Kafka 反序列化漏洞 (CVE-2023-34040)

zhi.oscs1024.com​​​​​ 漏洞类型反序列化发现时间2023-08-24漏洞等级中危MPS编号MPS-fed8-ocuvCVE编号CVE-2023-34040漏洞影响广度小 漏洞危害 OSCS 描述Spring Kafka 是 Spring Framework 生态系统中的一个模块&#xff0c;用于简化在 Spring 应用程序中集成 Apache Kaf…

【C++心愿便利店】No.2---函数重载、引用

文章目录 前言&#x1f31f;一、函数重载&#x1f30f;1.1.函数重载概念&#x1f30f;1.2.C支持函数重载的原理 -- 名字修饰 &#x1f31f;二、引用&#x1f30f;2.1.引用的概念&#x1f30f;2.2.引用特性&#x1f30f;2.3.常引用&#x1f30f;2.4.使用场景&#x1f30f;2.5.传…