【C语言】指针

news2024/9/22 5:38:48

文章目录

  • 指针
  • 作为参数的指针
  • 访问某个地址上的变量*
  • 指针的应用
  • 数组和指针
  • 数组变量是特殊的指针
  • 指针常量和常量指针
  • 数组指针和指针数组
  • 常见错误
  • 指针运算
  • 动态内存分配


指针

一般用p来表示一个指针,来自pointer

一个指针类型的变量就是保存地址的变量。
变量的值是内存的地址
普通变量的值是实际的值
指针变量的值是具有实际值的变量的地址

取地址运算符&
取值运算符*

int* p=&i;//表示p是一个指针,它指向的是一个int,现在把i的地址交给这个p指针
int* p,q;//无论*号靠近int还是靠近p,都只是表示p是个指针,q不是一个指针是一个普通变量
int *p,q;
int *p,*q;//p和q前面都有一个*号才表示p和q都是指针

作为参数的指针

void f(int *p);//f函数要一个int的指针
//在被调用的时候得到了某个变量的地址
int i=6;
f(&i);
//在函数里面可以通过这个指针访问外面的这个i

在这里插入图片描述
变量i里面存放了6,地址是70,把里面的地址取出交给f函数里面的变量p,p的值是70,于是可以说p是一个指针指向了i这个变量。

访问某个地址上的变量*

*是一个单目运算符,用来访问指针的值所表示的地址上的变量

例:*p表示变量i的值6
在这里插入图片描述

可以做左值也可以做右值。

int k=*p;
*p=k+1;

指针的应用

1、指针返回多个结果
① 函数返回值返回结果只能返回一个
② 函数返回多个值,某些值就只能通过指针返回,传入的参数实际上是需要保存带回的结果的变量

2、函数返回运算的状态,结果通过指针返回
① 常用的套路是让函数返回特殊的不属于有效范围内的值来表示出错:-1或0 (在文件操作会看到大量的例子)。
② 但是当任何数值都是有效的可能结果时,就得分开返回了。
③ 后续的语言(C++,Java) 采用了异常机制来解决这个问题。

数组和指针

函数参数表中的数组实际上是指针,数组名代表数组首地址的值。

a为数组首元素的地址; &a为整个数组的地址。

sizeof(a) == sizeof(int*)

可以用数组的运算符[]进行运算

int sum(int *ar,int n);
等价于:
int sum(int ar[],int n);

int sum(int *,int);
等价于:
int sum(int [],int);

//不是表示类型等价,是表示在参数表中出现是等价的。

数组变量是特殊的指针

数组变量本身表达指针:

int a[10];
int *p=a;//数组变量本身表达指针,无需用&取地址

数组单元表达的是变量:

a==&a[0];//数组单元表达的是变量,需要用&取地址

[]运算符可以对数组做,也可以对指针做:

p[0] 等价于 a[0]

*运算符可以对指针做,也可以对数组做:

*a=25;

数组变量是const的指针,不能被赋值:

int a[];
等价于
int *const a;

const int a[] = {I,2,3,4,5,6};
数组变量已经是const的指针了,这里的const表明数组的每个单元都是const int,所以必须通过初始化进行赋值。

保护数组值
因为把数组传入函数时传递的是地址,所以那个函数内部可以修改数组的值,为了保护数组不被函数破坏,可以设置参数为const

int sum(const int a[], int length);

指针常量和常量指针

指针常量——指针类型的常量(int *const p)
本质上是一个常量,指针用来说明常量的类型,表示该常量是一个指针类型的常量。在指针常量中,指针自身的值是一个常量,不可改变,始终指向同一个地址。

int a=10;
int *const p=&a;
p++;//报错,p指向的地址是一定的
*p=30;//p指向的地址是一定的,但其指向的内容可以修改

常量指针——指向“常量”的指针(const int *p,int const *p)
本质上是一个指针,常量表示指针指向的内容,说明该指针指向一个常量。在常量指针中,指针指向的内容是不可改变的,指针看起来好像指向了一个常量。

int a=10;b=20;
const int *p=&a;
p=&b;//指针可以指向其他地址,但是内容不可以改变
*p=30;//报错,指针的内容不可以改变

数组指针和指针数组

数组指针——指向数组的指针

指针数组——装着指针的数组

常见错误

地址变量没有被赋值之前,没有得到任何实际变量的地址之前,不能通过它用*访问任何的数据。

指针运算

这些算术运算可以对指针做:
给指针加、减一个整数(+, +=, +, -=)
递增递减(++/–)
两个指针相减……

  • 指针+1

给一个指针+1表示要让指针指向下一个变量
如果指针不是指向一片连续分配的空间,
如数组,则这种运算没有意义。

int a[]={1,2,3,4,5};
int *p=a;
printf("%p\n",p+1);//指针值+1实际上加的是sizeof

//*p等价于a[0], *(p+n)等价于a[n]
printf("%d\n",*(p+1));
等价于
printf("%d\n",a[1]);
  • 两个指针相减
//得到的是在该范围内数组范围内的元素的个数
int a[]={1,2,3,4,5};
int *p=a;//同int *p=&a[0];
int *p1=&a[5];
printf("%d\n",p1-p);

输出:5

//得到指针相减的字节大小
int b=(int)p1-(int)p;
printf("%d\n",b);

输出:20  //一个int型元素是4个字节,一个char型元素是1个字节
  • *p++

① 取出p所指的那个数据来,完事之后顺便把p移到下一个位置去
② *的优先级虽然高,但是没有++高
③ 常用于数组类的连续空间操作
④ 在某些CPU上,这可以直接被翻译成一条汇编指令

  • 指针比较

<, <=, ==, >, >=, != 都可以对指针做
比较它们在内存中的地址
数组中的单元的地址肯定是线性递增的

  • 0地址

① 当然你的内存中有0地址,但是0地址通常是个不能随便碰的地址,所以你的指针不应该具有0值,因此可以用0地址来表示特殊的事情:
返回的指针是无效的
指针没有被真正初始化(先初始化为0)
② NULL是一个预定定义的符号,表示0地址
③ 有的编译器不愿意你用0来表示0地址

  • 指针的类型

① 无论指向什么类型,所有的指针的大小都是一样的,因为都是地址
② 但是指向不同类型的指针是不能直接互相赋值的,这是为了避免用错指针

char a[]={1,2,3,4,5};
int a[]={1,2,3,4,5};
char *p=a;
int *q=b;
*q=0;
p=q;
//p指向char类型,一个char类型元素占1个字节,
//q指向int类型,一个int类型元素占4个字节,
//q给p赋值会导致p[0]-p[3]都被赋值

在这里插入图片描述

  • 指针的类型转换

① void表示不知道指向什么东西的指针,计算时与char相同(但不相通);
② 指针也可以转换类型
int p = &i; voidq = (void*)p;
这并没有改变p所指的变量的类型,而是让后人用不同的眼光通过p看它所指的变量:我不再当你是int了,我认为你就是个void!

  • 用指针来做什么

① 需要传入较大的数据时用作参数;
② 传入数组后对数组做操作;
③ 函数返回不止一个结果,如swap();
④ 需要用函数来修改不止一个变量;
⑤ 动态申请的内存……

动态内存分配

  • malloc

void* malloc(size_ t size);
向malloc申请的空间的大小是以字节为单位的,返回的结果是void*,需要类型转换为自己需要的类型
(int*)malloc(n*sizeof(int));

#include<stdlib.h>//需要加头文件<stdlib.h>

int *a=(int*)malloc(n*sizeof(int));
//(int*)强制装换为int类型,molloc需要的参数是这个数组占据的空间,以字节为单位的,所以用乘以sizeof()

free(a);//释放空间
  • free

① 把申请得来的空间还给系统,申请过的空间,最终都应该要还;
② 只能还申请来的空间的首地址,malloc申请来的地址原封不动的,怎么借来的怎么还!!!
③ free(NULL)不会报错,这不会做任何事情。

  • 常见问题

① 申请空间了没free,长时间运行内存逐渐下降;
② free过了再free;
③ 地址变过了,直接去free。


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

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

相关文章

windows x32调用门实现 ring3提权

概述 调用门是Intel提供的一个机制&#xff0c;用于控制不同权限级(ring0-ring3)的程序函数调用。简单点就是提供了一个ring3 调用ring0 函数的机制。 在intel手册volume3-Chapter 5.83描述如下 Call gates facilitate controlled transfers of program control between dif…

算法笔记(25)win10系统安装tensorflow-GPU环境亲测好用

环境准备 首先你的电脑得有GPU显卡&#xff0c;然后在tensorflow官网&#xff08;在 Windows 环境中从源代码构建 | TensorFlow&#xff09;找到各安装软件对应的版本&#xff0c;版本不对应将会导致安装失败。 标本机GPU显卡版本题本文选择的是官网最新的组合&#xff1a;p…

cubeIDE开发, stm32窗口看门狗WWDG的CubeMX配置及HAL库底层实现分析

一、stm32的WWDG说明 1.1 WWDG特点&#xff1a; 在前一篇博文介绍独立看门狗时就指出STM32 MCU提供两个看门狗&#xff0c;独立看门狗和窗口看门狗。 cubeIDE开发&#xff0c; stm32独立看门狗IWDT的CubeMX配置及HAL库底层实现分析_py_free的博客-CSDN博客 相比独立看门狗&am…

【C语言】数据类型

文章目录c语言的类型整数整数类型整数的内部表达整数的范围unsigned整数的格式化浮点型浮点类型输入输出输出精度字符类型逃逸字符类型转换自动类型转换强制类型转换逻辑类型bool逻辑运算条件运算符C语言的变量&#xff0c;必须在使用前定义&#xff0c;并且确定类型&#xff1…

ubuntu下使用doxygen生成软件文档

ubuntu下使用Doxygen生成软件文档一、软件下载1.系统安装Doxygen2.Vscode插件安装二、软件配置三、文档生成1.方法1&#xff1a;使用Doxygen-gui生成&#xff08;推荐&#xff09;2.方法&#xff1a;采用Doxygen命令&#xff08;不推荐&#xff09;另外Windows下使用方法提示&a…

【JavaScript】 Date 日期对象概述及相关方法

文章目录【JavaScript】 Date 日期对象的创建及相关方法一. 日期对象的创建二. 日期对象的相关方法三. 时间戳案例案例1&#xff1a;在页面上展示一个时钟&#xff0c;隔1s更新一次案例2&#xff1a;距离除夕倒计时【JavaScript】 Date 日期对象的创建及相关方法 一. 日期对象…

ArcGIS基础:构建点对连线表达点集内部相互关系

原始数据如下&#xff0c;为普通的点图层&#xff0c;总共是21个点。 点位分布如下&#xff1a; 属性表打开如下&#xff1a; 下面使用【构造视线】工具进行操作&#xff0c;其工具位于【3D分析工具】下的【可见性】工具栏。 打开【构造视线】对话框&#xff0c;把【视点…

Leetcode【494. 目标和】

题目描述 给你一个整数数组 nums 和一个整数 target 。 向数组中的每个整数前添加 ‘’ 或 ‘-’ &#xff0c;然后串联起所有整数&#xff0c;可以构造一个 表达式 例如&#xff0c;nums [2, 1] &#xff0c;可以在 2 之前添加 ‘’ &#xff0c;在 1 之前添加 ‘-’ &…

第10章 角色页的分页、排序、查询实现

1 重构WebApi.Controllers.RoleController. PostRolePageByFromBodyAsync //把所有符合条件的角色实例&#xff0c;按照指定字段进行排序操作。 if (!string.IsNullOrEmpty(pagination.OrderByFiled)) { var _obj JsonConvert.DeserializeAnonymousType(pagination.OrderByFil…

力扣 2351. 第一个出现两次的字母

题目 给你一个由小写英文字母组成的字符串 s &#xff0c;请你找出并返回第一个出现 两次 的字母。 注意&#xff1a; 如果 a 的 第二次 出现比 b 的 第二次 出现在字符串中的位置更靠前&#xff0c;则认为字母 a 在字母 b 之前出现两次。 s 包含至少一个出现两次的字母。 …

TopK问题的必会解法

目录经典解法&#xff0c;创建K个大小的堆不考虑空间的暴力排序做法不考虑空间的快排partition变形减治法思想(核心&#xff1a;找第K大的数)空间有限放不下&#xff0c;海量数据的分治法经典解法&#xff0c;创建K个大小的堆 传统的直接建立一个K个元素的小顶堆&#xff0c;类…

推荐两款可以将图片无损放大的在线工具

文章目录一、waifu2x网站预览传送地址二、BigJPG网站预览传送地址好不容易找到合适的图片素材但尺寸太小&#xff1f;那这里的工具正好适合你&#xff0c;能把你的小图放大几倍都不模糊。 一、waifu2x 本程序使用卷积神经网络对动漫风格的图片进行放大操作&#xff08;支持照…

再聊一下那 SQLSERVER 行不能跨页的事

一&#xff1a;背景 1. 讲故事 上一篇写完了之后&#xff0c;马上就有朋友留言对记录行的 8060byte 限制的疑惑&#xff0c;因为他的表记录存储了大量的文章&#xff0c;存储文章的字段类型用的是 nvarchar(max)&#xff0c;长度很显然是超过 8060byte 的&#xff0c;请问这个…

win10搭建 IIS 服务器

第一步: 打开程序和功能 找到 Internet 这个 勾选web管理工具和万维网服务 第二步: 在本地电脑创建一个文件夹(不要有中文空格等特殊字符) index.html 是默认访问的网址 第三步 关联访问的链接 选择本地物理路径 访问测试 第四步 修改绑定端口 第五步 修改防火墙 …

Linux | 文件操作的系统调用 open() read() write()

1. 基本含义辨析 文件操作的系统调用 open read write close &#xff08;系统调用&#xff1a;实现在内核中【用户态->内核态】—“陷入内核”&#xff09; man&#xff1a; 1 命令 2 系统调用 3 库函数 C操作文件的库函数 fopen fread fwrite fclose &#xff08;fo…

一个有意思的图片鼠标切换

做淘宝活动页面的时候&#xff0c;用到最多的就是锚点&#xff0c;一个图片标签&#xff0c;然后不断地在上面画热区。不过我想问的是有多少人研究过&#xff0c;用矩形画热点&#xff0c;四个坐标值各自表示的含义&#xff0c;还有它和background-position有什么相同或相似的地…

JavaWeb:RequestResponse的概述

1&#xff0c;Request和Response的概述 Request是请求对象&#xff0c;Response是响应对象。 这两个对象在我们使用Servlet的时候有看到&#xff1a; 此时&#xff0c;我们就需要思考一个问题request和response这两个参数的作用是什么&#xff1f; request&#xff1a;获取请…

RapidUp: Multi-Domain Permutation Protocol for Lookup Tables学习笔记

1. 引言 前序博客有&#xff1a; PLOOKUPPLOOKUP代码解析Efficient polynomial commitment schemes for multiple points and polynomials学习笔记PLONK PLOOKUPPlonKup: Reconciling PlonK with plookupPLONK: permutations over lagrange-bases for oecumenical nonintera…

2022年就要过去了,我的这份成绩单请您查收……

喜迎元旦岁月不居&#xff0c;时节如流年关交迭在即在2022行将尾声的此时想静静地坐下片刻和关注了云和恩墨这么久的老朋友们细数一遍这光阴里的纷纷呈呈这一年&#xff0c;充满了挑战与艰辛但所有努力和守望终有结果收成这一年&#xff0c;我们全心投入产品研发收获了更多的荣…

【隔离器使用说明】光隔、磁隔、容隔三兄弟介绍

文章目录前言一、三种常用隔离技术1. 光隔离2. 变压器隔离/磁隔3. 电容隔离二、隔离器重要指标1. 隔离电压值2. 爬电距离3. 共模瞬变抗扰度CMTI三、隔离器性能对比总结前言 本文简单介绍常用隔离器的类型和特点&#xff0c;是根据网络知识整理出来的 有错误的话请一定评论留言…