首页 > 其他分享 >指针基础知识

指针基础知识

时间:2024-09-27 15:18:55浏览次数:9  
标签:变量 指向 int 基础知识 ++ 地址 指针

指针基础知识

一、 资源链接

二、实参与形参

在 C/C++ 中,参数传递涉及到实参和形参两个概念:

  1. 实参(实际参数)

    • 实参是在函数调用时传递的具体值。
    • 它可以是常量、变量或表达式,但必须具有确定的值。
    • 在函数调用中,如果传递的是一个数组名,则传递的是该数组的首地址。
  2. 形参(形式参数)

    • 形参数在函数的定义中指定,用于接收传递给函数的值。
    • 形参必须指定类型,并只能是简单变量或数组,不能是常量或表达式。
    • 形参类型与实参必须一致,个数和顺序也需要保持相同。如果类型不一致,C/C++ 会自动将实参转换为形参的数据类型。

2.2 值传递与地址传递

  1. 值传递

    • 当函数被调用时,实参的值被传递给形参。
    • 这种传递是单向的,实参和形参占据不同的存储单元。
    • 形参的改变不会影响到实参的值,即形参变化不反映在主调函数中。
  2. 地址传递

    • 如果函数接收的是指针或者数组名(等价于指向第一个元素的地址),形参实际上接收的是地址,这使得实参可以被修改。

2.3 内存分配与函数调用

  • 内存分配

    • 在函数未被调用时,形参不占用内存。
    • 函数调用时,系统会分配内存给形参,并将实参的对应值复制到形参中。
  • 调用结束后

    • 函数执行完之后,其形参和返回值的内存会被释放。

小结

  • 数据传递的本质是通过“值传递”的方式进行的,意味着在函数调用时,由系统在内存中新开辟区域用于计算操作。
  • 当函数调用结束,其形参和返回值的内存将自动释放,确保内存资源的回收利用。

三、指针的概念定义及引用

3.1 指针的概念与定义

指针简介

在 C 语言中,指针是一个关键概念。它允许程序员直接操作内存地址,从而实现强大的功能和灵活性。理解指针的工作原理对于编写高效的 C 代码至关重要。

什么是指针?
  1. 内存地址

    • 在计算机中,每个变量都被存储在内存中一个唯一的地址上。这个地址可以用来访问和操作存储在那里的变量。
  2. 指针的定义

    • 指针是一个变量,用于存储另一个变量的内存地址。换句话说,指针的值指向的是另一个变量在内存中的位置。
指针的使用与语法
  1. 基本声明
    • 通过指针声明,可以创建一个用于保存内存地址的变量。例如:
int i = 3;          // 声明一个整数变量 i,值为 3
int *i_pointer = &i; // 声明一个指针变量 i_pointer,存储变量 i 的地址
  1. 解引用
    • 使用解引用操作符(*)可以访问指针指向的变量的值。
int value = *i_pointer; // 获取指针 i_pointer 指向的变量 i 的值,结果为3
运算符的使用
  1. 地址取运算符(&):
    • 用于获取一个变量的内存地址。
int *p = &i; // 获取变量 i 的地址,并存储在指针 p 中
  1. 解引用运算符(*):
    • 用于访问指针所指向地址的内容。
int value = *p; // 访问指针 p 指向的整数的值
定义和初始化指针变量
  1. 类型匹配
    • 定义指针变量时,必须确保指针的类型与其指向的变量类型匹配。例如:
int *p1, *p2; // 定义两个整数指针
int a = 10, b = 20;
p1 = &a;      // 将变量 a 的地址赋给指针 p1
p2 = &b;      // 将变量 b 的地址赋给指针 p2
  1. 错误示例
    • 不能直接将整数赋值给指针,也不能将地址赋给一个非指针类型的变量。

3.2 指针的值交换和地址交换

在C语言中,可以使用指针来交换两个变量的值(值交换)或者交换两个指针的指向(地址交换)。

  • 值交换:通过指针解引用改变指针指向的值。
void swapValues(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}
  • 地址交换:通过交换指针本身的值,使它们指向不同的变量。
void swapPointers(int **p1, int **p2) {
int *temp = *p1;
*p1 = *p2;
*p2 = temp;
}

3.3 C++中的引用与指针之间的关系

引用是指针的一个高级抽象,简化了某些内存操作。

定义引用的注意事项
  • 初始化要求:引用在定义时必须初始化。以下示例是错误的:
int &b; // 错误,引用必须初始化
  • 不可重新绑定:引用一旦被初始化,无法重新绑定至其他对象。
  • 数组引用限制:数组不能直接定义引用,因为数组表示一组数据,而引用只能作为单一对象的别名。
引用 vs 指针

引用和指针有几个关键区别:

  1. 不存在空引用:引用必须指向有效内存,而指针可以为 NULL。
  2. 不可重新绑定:引用在初始化后不允许指向别的对象,指针则可以随意调整指向。
  3. 初始化要求:引用在声明时需立即初始化,指针则可延迟。
引用的应用
  • 函数参数传递:引用作为函数参数可以避免值传递时的复制开销,并简化接口设计。相比指针,引用语法上的简便使得代码更易读。

3.4 数组与指针之间的关系

  • 数组名作为指针:数组名可以当作指向其首元素的指针。在函数定义中 int sum(int[]) 等价于 int sum(int*)
  • 数组变量的地址:数组名本身表示地址,不需要 & 取地址。
int a[10];
int *p = a; // 等同于 int *p = &a[0];
  • 数组单元地址获取:需要&以获得具体数组元素的地址。
a == &a[0]; // true
  • 数组和指针运算[] 运算符即可以作用于数组,也可用于指针。
p[0] <==> a[0];

3.5 指针与常量

  • 指向常量的指针const int *p1int const *p2指针指向的内容不可变。

  • 常量指针int *const p3表示指针本身不可变,但其指向的内容可变。

常量转换
  • 可以把非const变量的地址传给接受const指针的函数参数,以保护函数内不修改该值。然而,const变量的值不能被修改。

3.6 指针算术与运算

  • 指针+1:使指针指向下一个相邻的内存单元。
int a[10];
int *p = a;
*(p+1) ==> a[1];
  • 应确保指针指向连续空间如数组,才能有效进行算术运算。
指针自增和其他运算
  • *p++:获取指针当前值后,再令指针指向下一个元素。这种操作在某些硬件上能简化为一条指令,提高效率。
指针比较
  • 指针可以进行大小比较(<, <=, ==, >, >=, !=),需注意比较的是内存地址。

3.7 特殊的 0 地址

  • 内存中有可能存在地址 0,但通常不可直接使用。
  • 在指针中,0 地址或 NULL 表示特殊情况,比如未初始化的指针。
  • 使用 NULLnullptr(C++11 引入)来表示一个空指针更为稳妥。

3.8 指针的类型

  • 统一大小:在多数系统中,所有指针的大小是相同的,因为它们存储的是内存地址。
  • 类型安全:指向不同类型的指针不能相互赋值。这是因为指针类型定义了内存的解析方式。
  • 指针类型正确性:应避免错误使用指针类型,以防止不期望的行为。

3.9 动态内存分配与指针的类型转换

  • void*** 指针**:

    • void* 表示指向未知类型的通用指针,可以用来进行各种类型指针之间的转换。
    • 需要显式类型转换才能用于计算或者存储特定类型数据值。
  • 指针类型转换

    • 可以通过类型转换运算符将不同类型的指针相互转换。
int *p = &i;
void *q = (void*)p;
- 这种转换不会改变指针实际指向的数据类型,只是改变了对指针的解释方式。

3.10 使用指针的场景

  • 数据传递:用于传递较大的数据以避免变量拷贝。

  • 数组操作:传递数组指针以便函数对数组进行操作。

  • 函数多结果返回:通过传入指针参数的方式从函数返回多个结果。

  • 动态内存管理:申请和管理动态

四、a++++aa = a + 1 的区别(题外)

以下是对 a++++aa = a + 1 的区别和用法进行的整理:

操作
类型
操作描述
返回值
a = a + 1
赋值语句
直接将 a 的值增加 1
无返回值
a++
表达式
返回 a 自增前的值,在表达式求值后将 a 增加 1
a 增加前的原始值
++a
表达式
在表达式求值前将 a 增加 1,然后返回增加后的值
a 增加后的新值

三者的共同点

a++++aa = a + 1 都会使变量 a 的值增加1。

各自区别

a = a + 1
  • 类型:赋值语句。

  • 操作:直接将 a 的值增加1。

  • 返回值:无返回值,因为赋值语句不返回值。

a++(后缀自增)
  • 类型:表达式。

  • 操作:返回 a 自增前的值,在表达式求值后将 a 增加1。

  • 返回值a 增加前的原始值。

++a(前缀自增)
  • 类型:表达式。

  • 操作:在表达式求值前将 a 增加1,然后返回增加后的值。

  • 返回值a 增加后的新值。

表达式中的用法和语义

  • 当这几个操作独立使用时,它们的共同点是都能使 a 增加1。

  • 在复杂表达式中,a++++a 的区别在于:

    • a++ 将参与计算的值是原始值。
    • ++a 将参与计算的值是增加后的新值。

结论

  • a++++a 都涉及自增操作,区别在于自增时机以及参与表达式计算的值。

  • a = a + 1 是明确的赋值操作,并不会参与其他表达式中作为计算的一个部分。

标签:变量,指向,int,基础知识,++,地址,指针
From: https://blog.csdn.net/tkhhhhh/article/details/142594781

相关文章

  • 【重生之我】初学C语言之 指针
    指针or地址???指针概念C语言中每个内存单元都有一个编号,有了这个内存单元的编号,CPU就可以快速找到一个内存空间,储存空间中一个字节里面能存放8个比特位。bitBYTEKBMBGBTB比特字节(8bit)1024字节1024KB1024MB1024GB内存单元的编号==地址==指针Cpu从内存单元中拿数据,Cpu算完后数据再储存在......
  • Python 迭代器双指针
    我们知道在cpp这种指针语言里面,双指针是这么写的:for(autoi=v.begin(),j=v.begin();j<v,end();j++){//dosomething...//updatepointeriwhile(cond){i++;}}对于py这样不带指针的,一般就只能这么写:i=0forjinrange(len(lst)):#do_something......
  • 基本双指针问题
    c++数据结构p2#include<iostream>#include<stdlib.h>#include<time.h>usingnamespacestd;//奇偶数调整问题//整型数组,把偶数调整到数组的左边,把奇数调整到数组的右边voidAdjustArray(intarr[],intsize){ int*p=arr; int*q=arr+size-1; //p->......
  • 虚函数,虚函数表,虚表指针,覆盖
    1、虚函数在成员函数前面加virtual后,该函数就称为虚函数,此时该类就会像虚继承一样多了一个虚表指针(虚函数表指针、虚指针)2、虚函数表虚表指针指向的是属于该类的一张表格的首地址,该表格中记录了该类的所有虚函数的首地址    如果类中没有其他成员变量    ......
  • 一些常用tricks,基础知识收录
    uoj转,YAML的ppt格式不想改了,将就看看吧|一些常用tricks,基础知识收录byzsjchildren:|题目链接:T1:CF504EMishaandLCPonTreeT2:LuoguP2617DynamicRankingsT3:LuoguP4197PeaksT4:LuoguP4690[Ynoi2016]镜中的昆虫T5:H1079.E.‘MinamiKotori......
  • 【C++习题】2.双指针_移动零
    文章目录题目链接:题目描述:解法(快排的思想:数组划分区间-数组分两块):C++算法代码:图解题目链接:283.移动零题目描述:解法(快排的思想:数组划分区间-数组分两块):双指针算法,利用数组下标充当指针。我们可以用一个cur指针来扫描整个数组,另一个dest指针用来记......
  • 嵌入式项目:STM32平衡车详解 (基础知识篇) (基于STM32F103C8T6)
    前言:本文是基于B站草履虫编写的平衡车相关内容,包括模块和基础知识,结合代码进行讲解,将知识进行汇总(由于本篇内容较长,请结合目录使用)注:基于开源精神,本文仅供学习参考目录前言:本文是基于B站草履虫编写的平衡车相关内容,包括模块和基础知识,结合代码进行讲解,将知识进行汇总......
  • 掌握 JavaScript 运算符:从基础知识到按位
    在本博客中,我们将深入探讨javascript运算符的世界,涵盖从基本算术到按位运算的所有内容。我们将探讨“一元”、“二元”和“操作数”等术语,并提供实际示例来帮助您理解每个概念。让我们开始吧!基本运算符一元、二元和操作数一元运算符?作用于单个操作数(例如,x)。二元运算符?作......
  • RabbitMQ基础知识
    1.1什么是MQ?消息队列(MessageQueue),是基础数据结构中“先进先出”的一种数据结构。一般用来解决应用解耦、异步消息、流量削峰等问题,实现高性能、高可用、可伸缩和最终一致性架构。RabbitMQ可以理解为一个邮箱,或者一个邮局,或者是一个邮递员,保证“张三”的信件最终传递......
  • 开发人员人工智能入门:揭秘基础知识部分
    开发者们大家好!人工智能不再只是一个梦想。它就在这里并改变我们构建软件的方式。它可以使应用程序更好、更有用。但如何开始在项目中使用人工智能呢?本系列旨在为您提供踏上人工智能开发之旅的基础知识。在第一部分中,我们将深入研究核心概念并提供使用langchain和openai的实践......