C语言----指针

目录

1.概念

2.格式

3.指针操作符

4.初始化

1. 将普通变量的地址赋值给指针变量

a. 将数组的首地址赋值给指针变量

b. 将指针变量里面保存的地址赋值给另一个指针变量

5.指针运算

5.1算术运算

5.2 关系运算

指针的大小

总结:

段错误

指针修饰

1. const修饰

2. void

大小端

二级指针

指针和数组

1. 指针和一维数组

直接访问:

间接访问:

2. 指针和二维数组

直接访问:

间接访问:

数组指针

数组指针

定义:本质是指针,指向的是数组(又称行指针)

格式:存储类型数据类型(*指针变量名)[列数];

大小


指针的优点:

  1. 使程序更加简洁、紧凑、高效
  2. 有效的表达更复杂的数据结构
  3. 动态分配内存
  4. 得到多余一个数的函数的返回值

1.概念

地址:内存中每个字节单元都有点编号

指针:指针就是地址

指针变量:用于存放地址的变量叫做指针变量

2.格式

存储类型 数据类型 * 指针变量名

int* p;

使用:

int a=5;

int* p=&a;

char ch=‘t’;

char* p=&ch;

3.指针操作符

&:取地址符--->取变量的地址

*:取内容 --->取地址里面的内容

*&a==a;// *和&是互逆运算

// a是变量就是错的,a是地址就是对的

&*a

4.初始化

指针变量只使用前不仅要定义还要初始化,未初始化的指针变量是不能随便使用的,会产生野指针

int* p;

1. 将普通变量的地址赋值给指针变量

int a=10;
1)int* p=&a;//定义的同时赋值
2)int* p=NULL;//先定义指针变量在进行赋值
p=&a;

int* p = NULL; // int *p
p = &a;
printf("%d %d\n", a, *p);  // 打印 a 的值 10 10
printf("%p %p\n", &a, p);  // 打印 a 的地址

*p = 3;
printf("%d %d\n", a, *p);  // 打印 a 的值 3 3
printf("%p %p\n", &a, p);  // 打印 a 的地址
a. 将数组的首地址赋值给指针变量

char str[10] = "hello";

char* p = str; // 指针指向数组的首地址,指向字符'h'的地址

b. 将指针变量里面保存的地址赋值给另一个指针变量

floatf = 1.3;

float* p = &f;

float* q = p;

5.指针运算

5.1算术运算

char str[32] = "hello";

char* p = str;

p++; // 指针向高地址方向移动一个数据单位(看数据类型),指针指向发生变化

p--; // 指针向低地址方向移动一个数据单位(看数据类型),指针指向发生变化

int* p; p++;// 移动4字节

double*p; p++; // 移动8字节

p+n:访问高地址方向第n 个数据的地址,指针指向不会发生变化

p-n:访问低地址方向第n 个数据的地址,指针指向不会发生变化

偏移了多少地址(字节) = n *sizeof(数据类型)

两个地址之间的差 = 两个地址之间相隔元素的个数

q - p=两个地址之间相隔的元素个数

char str[] = "hello";

char* p = str;

char* q = p+3;

printf("%d\n", q - p);

5.2 关系运算

> < == !=

指针之间的关系运算比较的是它指向地址的高低

高地址的指针大于低地址的指针

char str[32] = "hello";

char* p1 = &str[1];
char* p2 = &str[3];

p2 > p1
    
注意:指向不同类型的数组指针关系运算没有意义,指向不同区域的指针关系运算也没有意义
(同一个数组间进行比较)

指针的大小

int a = 5;
int* p = &a; // 4
short b = 2;
short* p1 = &b;  // 4
double c = 1.1;
double* p2 = &c;  // 4

szieof(指针变量名)

32位操作系统:指针为4字节
8位16进制表示,4字节

64位操作系统:指针为8字节
16位16进制表示,8字节

总结:

1.32位操作系统:指针为4字节, 64位操作系统:指针为8字节

2. 内存地址是固定的,但是变量的地址不固定的(栈区随机分配)

3. 指针类型根据指针指向空间的数据类型

段错误

Segentation fault (core dumped

1) 野指针,没有规定指向的指针会在内存中乱指,野指针产生原因

1. 指针变量定义没赋值

2. 指针 p被 free之后,没有置 NULL,会让人以为p是合法指针

解决:int* p = NULL;

2)内存泄漏,对非法空间进行赋值

指针修饰

1. const修饰

1) const int num = 10;

const int num = 10;

num = 3;

int* p = &num;

*p = 3; // 可以

2)const int *p;//修饰*p,指针指向的内容不能更改,指针指向可以修改

int const *p; //也可以这样修饰*p

int num=10;

const int* p=&num;

*p=20;//错误,因为*p被修饰

int sum=20;

p=&sum;//可以

3)int* const p;//修饰p,指针的指向不能修改,但是指针指向的内容可以修改

int num=10;

int sum=20;

int* const p=&num;

p=*sum;//错误

*p=20;//可以

4)修饰函数参数

2. void

void num;//不允许修饰变量

void* p; //p是任意类型的指针,需要强转才能使用
    使用场景:函数参数或者函数返回值
    注意:通过void类型指针进行取内容,需要对地址进行强转
    强转方式:void* p=NULL;强转(int*)p 取内容*((int* )p)
    

大小端

TCP协议(三次握手四次挥手){网编时应用}

在计算机进行超过1字节数据进行储存时,会出现存储数据顺序不同的情况即大小端储存

Big-Endian(大端字节序)大端:在低地址存放高字节数据,高地址存放低字节数据

Little-Endian(小端字节序)小端:在低地址存放低字节数据,高地址存放高字节数据

举例:存储数据 0x12345678,起始地址 0x4000

0x4000 0x4001 0x4002 0x4003

大端:0x12 34 56 78

小端:0x78 56 34 12

查看电脑是大端还是小端,代码如下:

int a = 0x12345678;
    char b;
    b = (char)a;
    printf("%#x\n", b);
    
    // 电脑是小端,网络是大端
	// 电脑向网络传输东西,数据要从小端变成大端,传出去
	// 网络向电脑传输东西,数据要从大端转成小端,接收过来

二级指针

一级指针:存放变量地址

二级指针:存放的是一级指针的地址

格式: 存储类型 数据类型 **指针变量名

int num = 10;

int *p = &num;

int **q = &p;

访问 num 的值:

num *p **q

访问 num 的地址:

&num p *q

访问 p 的地址:

&p q

指针和数组

直接访问:按变量的地址存取变量的值(通过数组名访问)

间接访问:通过存放变量地址的变量去访问变量(通过指针访问)

1. 指针和一维数组

int a[5] = {1, 2, 3, 4, 5};

int *p = arr;

直接访问

int a[5] = {1, 2, 3, 4, 5};
int *p = a;
printf("%p %p %p\n", a, a+1, a+3);  // 直接访问元素的地址
printf("%d %d\n", a[1], *(a+1));
间接访问:

int a[5] = {1, 2, 3, 4, 5};
int *p = a;

printf("%p %p %p\n", a, a+1, a+2);
printf("%p %p %p\n", p, p+1, p+2);
printf("%d %d %d\n", *p, *(p+1), *(p+2));
printf("%d %d %d\n", p[0], p[1], p[2]);
a 和 p 本质上不同,a地址常量, p是变量,a不能执行 ++ 操作,但是 p 可以

访问数组元素a[i]的值:
直接访问:a[i] *(a+i)
间接访问:p[i] *(p+i)

访问数组元素a[i]的地址:
直接访问:&a[i] a+i
间接访问:&p[i] p+i

inta[3] = {3, 2, 1};

int *p = a;

printf("%d\n", *p++);// 3在打印一次的话就是 2

printf("%d\n", *a++); //错误,a地址常量

运算方法:

1) ++和 *都是单目运算符,优先级相同

2) 单目运算符从右向左进行运算

int a[3] = {3, 2, 1};

int *p = a;

printf("%d\n",下列打印);

*(p++)// 3实际上指针指向到了第二个元素的地址

(*p)++// 打印出来是 3,实际上第一个元素值变成 4

++*p // 打印出来 4,自加完之后的值

++(*p) // 同上

*++p; // 2,先将指针向高地址方向移动一个数据单位,然后取地址内容

*(++p); // 同上

2. 指针和二维数组

int a[2][3]= {1, 2, 3, 4, 5, 6}; // a:数组名:表示第一行的首地址,a+1:第二行首地址

在a前面加*,表示将行地址降级为列地址

*a+0:第一行第一列的地址

*a+1:第一行第二列的地址

*(a+1):第二行第一列的地址

*(a+1)+1:第二行第二列的地址

a[0]:第一行第一列的地址

a[0]+1:第一行第二列的地址

a[1]:第二行第一列的地址

a[1]+1:第二行第二列的地址

直接访问:

间接访问:
数组指针

数组指针

定义:本质是指针,指向的是数组(又称行指针)

格式:存储类型数据类型(*指针变量名)[列数];

int a[2][3] = {1, 2, 3, 4, 5,6};

int (*p)[3] = a;

p:int (*)[3]; 运算三个三个运算

p可以代替a进行元素访问,但是本质不同

访问 a[i][j]的地址:

*(p+i)+j &p[i][j]p[i]+j

访问a[i][j]的元素

*(*(p+i)+j) *(p[i]+j)p[i][j]

大小

sizeof(p) ==4


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

青少年编程与数学 02-006 前端开发框架VUE 01课题、VUE简介

青少年编程与数学 02-006 前端开发框架VUE 01课题、VUE简介 一、前端开发一、前端框架二、Vue.js三、应用场景四、区别五、学习资源六、应用示例说明&#xff1a; 课题摘要:本文介绍了前端开发框架Vue.js的基本概念和特性。Vue.js是一个渐进式JavaScript框架&#xff0c;用于构…

STM32单片机芯片与内部57 SPI 数据手册 寄存器

目录 一、SPI寄存器 1、SPI控制寄存器 1(SPI_CR1)(I2S模式下不使用) 2、SPI控制寄存器 2(SPI_CR2) 3、SPI 状态寄存器(SPI_SR) 4、SPI 数据寄存器(SPI_DR) 5、SPI CRC多项式寄存器(SPI_CRCPR)(I2S模式下不使用&#xff09; 6、SPI Rx CRC寄存器(SPI_RXCRCR)(I2S模式下不…

QT-------------自定义插件和库

以下是一个使用 Qt 实现图表交互操作的示例&#xff0c;涵盖了自定义图表视图类、不同类型的柱状图和饼图等内容。 实现思路 自定义图表视图类&#xff1a;创建一个从 QChartView 派生的自定义类&#xff0c;用于处理图表的交互操作。主窗口设计初始化&#xff1a;在主窗口中…

【Python】闭包

闭包&#xff08;Closure&#xff09;是指一个函数记住了并可以访问它的词法作用域&#xff08;lexical scope&#xff09;&#xff0c;即使这个函数在词法作用域之外执行。 闭包其实就是延伸了作用域的函数&#xff0c;包括被延伸函数主体中引用的非全局变量和局部变量。这些…

矩阵运算提速——玩转opencv::Mat

介绍:用Eigen或opencv::Mat进行矩阵的运算&#xff0c;比用cpp的vector或vector进行矩阵运算要快吗? 使用 Eigen 或 OpenCV 的 cv::Mat 进行矩阵运算通常比使用 std::vector<int> 或 std::vector<double> 更快。这主要有以下几个原因&#xff1a; 优化的底层实现…

FastDeploy部署paddlecls分类模型(windows)

目录 写在前面 总体步骤 C SDK编译库 方式1&#xff1a;编译安装 方式2&#xff1a;下载预编译库 准备模型、文件、代码和数据 模型文件类型 samples代码 待预测图像 使用 FastDeploy C SDK 将cpp源码编译为exe 编写cpp代码 cpp代码编译exe 运行可执行程序exe 将…

【第二部分--Python之基础】03 容器类型的数据

Python内置的数据类型如序列&#xff08;列表、元组等&#xff09;、集合和字典等可以容纳多项数据&#xff0c;我们称它们为容器类型的数据。 序列 序列&#xff08;sequence&#xff09;是一种可迭代的、元素有序的容器类型的数据。 序列包括列表&#xff08;list&#xff…

linux shell脚本 【分支结构case...in 、循环结构、函数】内附练习

1.思维导图 2.练习 1.定义一个find函数&#xff0c;查找ubuntu和root的gid 2.定义一个数组&#xff0c;写一个函数完成对数组的冒泡排序 bubble() {n${#arr[*]}for((i0;i<n-1;i));dofor((j0;j<n-1-i;j));doif ((arr[j]>arr[j1]));thentemp${arr[j]}arr[j]${arr[j1]}a…

基于SpringBoot和OAuth2,实现通过Github授权登录应用

基于SpringBoot和OAuth2&#xff0c;实现通过Github授权登录应用 文章目录 基于SpringBoot和OAuth2&#xff0c;实现通过Github授权登录应用0. 引言1. 创建Github应用2. 创建SpringBoot测试项目2.1 初始化项目2.2 设置配置文件信息2.3 创建Controller层2.4 创建Html页面 3. 启动…

从单点 Redis 到 1 主 2 从 3 哨兵的架构演进之路

一、前言 我们有个项目中用的 MySQL、Redis、ES、微服务都是单节点部署的&#xff0c;没有做集群模式部署&#xff0c;为了提高整体的可用性&#xff0c;对项目的部署架构进行了升级&#xff0c;支持高可用。 二、部署拓扑图 我们项目的测试环境 12 台服务器已经部署好了&am…

SQL 中的 EXISTS

我们先从 SQL 中最基础的 WHERE 子句开始。 比如下面这条 SQL 语句&#xff1a; 很显然&#xff0c;在执行这条 SQL 语句的时候&#xff0c;DBMS 会扫描 Student 表中的每一条记录&#xff0c;然后把符合 Sdept IS 这个条件的所有记录筛选出来&#xff0c;并放到结果集里面去…

大型概念模型:在句子表示空间中的语言建模

《Large Concept Models: Language Modeling in a Sentence Representation Space》这篇论文介绍了一种新的语言模型方法&#xff0c;它在句子表示空间中进行建模。该方法旨在改进传统语言模型的局限性&#xff0c;通过捕捉更高级别的语义信息来提高自然语言处理任务的表现。 模…

活动预告 | Microsoft Power Platform 在线技术公开课:实现业务流程自动化

课程介绍 参加“Microsoft Power Platform 在线技术公开课&#xff1a;实现业务流程自动化”活动&#xff0c;了解如何更高效地开展业务。参加我们举办的本次免费培训活动&#xff0c;了解如何借助 Microsoft AI Builder 和 Power Automate 优化工作流。结合使用这些工具可以帮…

YK人工智能(三)——万字长文学会torch深度学习

2.1 张量 本节主要内容&#xff1a; 张量的简介PyTorch如何创建张量PyTorch中张量的操作PyTorch中张量的广播机制 2.1.1 简介 几何代数中定义的张量是基于向量和矩阵的推广&#xff0c;比如我们可以将标量视为零阶张量&#xff0c;矢量可以视为一阶张量&#xff0c;矩阵就是…

企业二要素如何用C#实现

一、什么是企业二要素&#xff1f; 企业二要素&#xff0c;通过输入统一社会信用代码、企业名称或统一社会信用代码、法人名称&#xff0c;验证两者是否匹配一致。 二、企业二要素适用哪些场景&#xff1f; 例如&#xff1a;信用与金融领域 1.信用评级&#xff1a;信用评级…

Visual Studio 2022安装教程

1、下载网址 Visual Studio 2022 IDE安装网址借助 Visual Studio 设计&#xff0c;具有自动完成、构建、调试、测试功能的代码将与 Git 管理和云部署融为一体。https://visualstudio.microsoft.com/zh-hans/vs/ 点击图片所示 双击运行 2、安装 点击C桌面开发&#xff08;右边…

TVS二极管选型【EMC】

TVS器件并联在电路中&#xff0c;当电路正常工作时&#xff0c;他处于截止状态&#xff08;高阻态&#xff09;&#xff0c;不影响线路正常工作&#xff0c;当线路处于异常过压并达到其击穿电压时&#xff0c;他迅速由高阻态变为低阻态&#xff0c;给瞬间电流提供一个低阻抗导通…

redis的集群模式与ELK基础

一、redis的集群模式 1.主从复制 &#xff08;1&#xff09;概述 主从模式&#xff1a;这是redis高可用的基础&#xff0c;哨兵和集群都是建立在此基础之上。 主从模式和数据库的主从模式是一样的&#xff0c;主负责写入&#xff0c;然后把写入的数据同步到从服务器&#xff…

Kubernetes第三天

1.pod容器的三种重启策略 查看容器的重启策略有哪些 kubectl explain po.spec. 发现有Always OnFailure Never Always,当容器退出时&#xff0c;始终重启容器 OnFailure,当容器正常退出时&#xff0c;不会自动重启容器&#xff0c;当容器异常退出时&#xff0c;重启容器 …

61.旋转链表 python

旋转链表 题目题目描述示例 1&#xff1a;示例 2&#xff1a;提示&#xff1a; 题解思路分析Python 实现代码代码解释提交结果 题目 题目描述 给你一个链表的头节点 head &#xff0c;旋转链表&#xff0c;将链表每个节点向右移动 k 个位置。 示例 1&#xff1a; 输入&#…