指针基础

简介: 指针基础

指针基础

指针是C语言中一个非常重要的概念,它允许程序直接访问和操作内存地址。下面将深入剖析指针的概念、声明、赋值及指针运算。

一、指针的概念

在计算机的内存中,每一个字节单元(可存储8个bit的数据)都有一个独特的编号,即地址。内存单元使用这个地址来标识自身的位置,而内存单元的地址就称作指针。专门用来存放内存单元地址的变量,称为指针变量。在不影响理解的情况下,常对地址、指针和指针变量不作区分,统称为指针。

二、指针的声明

指针变量和其他变量一样,使用之前需要先进行定义。指针的声明需要指定指针所指向的数据类型。例如:

int *p; // 声明一个指向整型数据的指针变量p

float *q; // 声明一个指向浮点型数据的指针变量q

char *s; // 声明一个指向字符型数据的指针变量s

在声明中,*是类型说明符的一部分,表示该变量是一个指针变量,而变量名前的类型说明符(如int、float、char)则指定了指针所指向的数据类型。

三、指针的赋值

指针变量的赋值只能赋予地址,不能赋予任何其他数据,否则将引起错误。在C语言中,可以使用地址运算符&来获取变量的地址,并将其赋给指针变量。例如:

int a = 10;

int *p = &a; // 将变量a的地址赋给指针变量p

指针变量也可以在声明时直接初始化,如:

int a = 10, *p = &a;

或者将一个指针变量的值赋给另一个指向相同类型数据的指针变量,如:

int b = 20, *pa = &a, *pb = pa; // pb也指向a

四、指针的运算

指针变量可以进行某些运算,但其运算的种类是有限的,主要包括赋值运算、算术运算和关系运算。

算术运算:

指针加1:表示指针所指向的地址加上sizeof(指针所指数据类型)的地址。例如,如果p是指向整型数组的指针,则p+1指向数组中下一个整型元素的位置。

指针加(减)整数n:将指针向前(或向后)移动n个数据元素的位置。

指针自增(++)和自减(--)运算:使指针向前或向后移动一个数据元素的位置。

指针相减:两个指向同一数组(或同一块连续内存区域)的指针相减,结果是它们之间相隔的元素个数。

关系运算:

指针之间可以使用<、<=、>、>=、!=、==等关系运算符进行比较。这种比较实质上是地址大小的比较。

解引用:

使用*运算符可以解引用指针,即获取指针所指向地址中的值。例如,*p就是获取指针p所指向地址中的值。

注意事项

指针变量在定义后必须初始化或赋值,否则使用未初始化的指针变量会导致未定义行为,甚至程序崩溃。

指针运算时,要注意指针的类型和它所指向的数据类型,因为指针运算的单位是它所指向的数据类型的大小。

指针变量之间不能直接进行算术运算(如相加、相乘等),除非它们指向同一数组或同一块连续内存区域,并且进行的是合法的指针算术运算。

指针和数组在C语言中有密切关系,指针可以指向数组的首地址,并通过指针访问数组元素。

通过深入理解和掌握指针的这些基本概念和运算规则,可以更好地利用C语言进行高效的内存管理和数据操作。

 

 

在深入探讨C语言中的指针概念、声明、赋值及运算时,我们首先需要明确指针在计算机内存管理中的核心地位。指针是C语言乃至众多编程语言中一项极为强大的工具,它允许程序直接访问和操作内存地址,从而实现对复杂数据结构的直接管理和操作。以下是对指针技术的详细解析,包括代码示例和技术性内容。

一、指针的概念

在计算机的内存中,每一个字节单元(可存储8个bit的数据)都有一个独特的编号,即地址。内存单元通过这个地址来标识自身的位置,而内存单元的地址就被称为指针。专门用来存放内存单元地址的变量,称为指针变量。在编程中,我们通常对地址、指针和指针变量不做严格区分,统称为指针。

二、指针的声明

指针变量在声明时需要指定其指向的数据类型。这是因为在C语言中,不同类型的数据占用的内存空间大小不同,因此指针在运算时(如指针加1)需要知道其指向的数据类型大小,以便正确地移动指针。指针的声明语法如下:

类型名 *指针变量名;

例如:

int *p; // 声明一个指向整型数据的指针变量p

float *q; // 声明一个指向浮点型数据的指针变量q

char *s; // 声明一个指向字符型数据的指针变量s

在这里,*是类型说明符的一部分,表示该变量是一个指针变量,而变量名前的类型说明符(如int、float、char)则指定了指针所指向的数据类型。

三、指针的赋值

指针变量的赋值只能赋予地址,不能赋予任何其他数据,否则将引起编译错误或运行时错误。给指针变量赋值的方法主要有两种:

 

直接通过地址运算符&获取变量的地址:

 

int a = 10;

int *p = &a; // 将变量a的地址赋给指针变量p

 

 

在声明时直接初始化:

 

int a = 10, *p = &a; // 声明整型变量a并初始化,同时声明并初始化指向a的指针p

 

或者,将一个指针变量的值赋给另一个指向相同类型数据的指针变量:

 

int b = 20, *pa = &a, *pb = pa; // pb也指向a

 

四、指针的运算

指针变量可以进行某些运算,但其运算的种类是有限的,主要包括赋值运算、算术运算和关系运算。

1. 赋值运算

赋值运算是最简单的指针运算,即将一个地址值赋给指针变量。

int *p, a = 10;

p = &a; // 将变量a的地址赋给指针p

2. 算术运算

指针的算术运算主要包括指针加(减)整数、指针自增(++)和自减(--)、指针相减。

 

指针加 1:表示指针所指向的地址加上sizeof(指针所指数据类型)的地址。

 

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

int *p = arr; // p指向arr的第一个元素

p++; // p现在指向arr的第二个元素

 

 

指针加(减)整数 n:将指针向前(或向后)移动n个数据元素的位置。

 

p = p + 2; // p现在指向arr的第三个元素

p = p - 1; // p现在指回arr的第二个元素

 

 

指针相减:两个指向同一数组(或同一块连续内存区域)的指针相减,结果是它们之间相隔的元素个数。

 

int *start = arr;

int *end = arr + 4; // 指向arr的最后一个元素

int length = end - start; // 长度为4,即两指针之间相隔的元素个数

 

3. 关系运算

指针之间可以使用<、<=、>、>=、!=、==等关系运算符进行比较。这种比较实质上是地址大小的比较。

int *p1 = arr;

int *p2 = arr + 2;

if (p1 < p2) {

printf("p1 is less than p2\n");

}

五、指针的高级应用

指针的强大之处在于

 

相关文章
|
IDE 关系型数据库 开发工具
使用Visual Basic进行Windows窗体开发
【4月更文挑战第27天】本文介绍了使用Visual Basic进行Windows窗体(WinForms)开发的步骤,从搭建开发环境到创建、设计用户界面,再到编写事件驱动的代码和数据绑定。Visual Basic结合WinForms提供了一种易学易用的桌面应用开发方案。通过调试、优化、部署和维护,开发者可以构建专业应用程序。随着技术发展,掌握最新UI设计和开发工具对于保持竞争力至关重要。本文为初学者提供了基础指导,鼓励进一步探索和学习。
482 0
|
存储 缓存 固态存储
|
SQL 索引 数据库
使用instr 函数优化替换Like条件子句提高数据检索性能案例总结
使用instr 函数优化替换Like条件子句提高数据检索性能
1342 0
使用instr 函数优化替换Like条件子句提高数据检索性能案例总结
|
人工智能 自然语言处理 数据处理
首次引入大模型!Bert-vits2-Extra中文特化版40秒素材复刻巫师3叶奈法
Bert-vits2项目又更新了,更新了一个新的分支:中文特化,所谓中文特化,即针对中文音色的特殊优化版本,纯中文底模效果百尺竿头更进一步,同时首次引入了大模型,使用国产IDEA-CCNL/Erlangshen-MegatronBert-1.3B大模型作为Bert特征提取,基本上完全解决了发音的bad case,同时在情感表达方面有大幅提升,可以作为先前V1.0.1纯中文版本更好的替代。
首次引入大模型!Bert-vits2-Extra中文特化版40秒素材复刻巫师3叶奈法
|
云安全 监控 安全
带你读《阿里云安全白皮书》(八)——云上安全重要支柱(2)
阿里云在其产品全生命周期中高度重视安全,特别是在设计环节,安全团队会进行全面的威胁建模和安全架构设计,确保产品在部署、网络、应用等各层面的安全性。阿里云具备一票否决权,确保所有产品在上线前都经过严格的安全审核。针对租户隔离问题,阿里云在虚拟化、网络、网关、应用和主机等多个层级实施了纵深防御体系,确保云环境的安全。
|
Prometheus Cloud Native Linux
Linux|错误集锦|prometheus Error on ingesting samples that are too old or are too far into the future的解决
Linux|错误集锦|prometheus Error on ingesting samples that are too old or are too far into the future的解决
851 0
Linux|错误集锦|prometheus Error on ingesting samples that are too old or are too far into the future的解决
|
Arthas 运维 监控
JVM学习.05 JVM常见的排障和调优
前面介绍了JVM相关的内存和线程相关的技术。对于JVM也算有了一个比较系统、完整的理论基础。理论总是作为指导实践的工具,但是从理论到实践,总会遇到一些虚拟机相关问题,故障。所以还需要学习一些常用的JVM排障工具,和一些常见的调优手段。
501 0
JVM学习.05 JVM常见的排障和调优
|
算法 搜索推荐
【双指针】:Leetcode283.移动零
【双指针】:Leetcode283.移动零
196 0
|
安全 Linux 网络安全
如何使用Nmap进行端口扫描和服务识别?
如何使用Nmap进行端口扫描和服务识别?
1373 0