C语言指针剖析一:指针的声明与访问

目录

前言

1:指针的定义

2:指针变量

2.1:const关键字

3:指针的指针


前言

在计算机中,所有的数据都是存放在存储器中的,一般把存储器的一个字节称为一个内存单元。不同的数据类型占用的内存单元是不同的。为了快速、准确的访问这些内存单元,计算机为每一个内存单元进行编号,内存单元的编号也就是内存单元的地址。C 语言中,把这个地址叫做指针。

 

1:指针的定义

指针的定义:指针是一种数据类型,基于该类型声明的变量称为指针变量,该变量存放的是内存中的某个地址,

指针的声明:类型 * 指针变量名;//如 int * pNum;“*”表示语句声明的是一个指针变量,类型指定了指针所指的内存单元的数据类型。可以将int*理解成一种复合类型,是指向 int 型数据的指针。

指针的初始化:声明指针变量时,C 并不会自动对其进行初始化,我们通过取地址符(&)给指针变量赋值是个有效的手段,实际上,可以在声明一个指针变量的同时完成其初始化。例如:int num=1; int *pN=#对于无处可指的指针变量,也要将其初始化为 NULL(即 0,空指针)。如:int *pa = NULL;

指针的引用:两个有关的运算符:

1) &:取地址运算符。

2) *:指针运算符(或称“间接访问” 运算符)。

C语言中提供了地址运算符&来表示变量的地址。其一般形式为:&变量名;如&a 表示变量 a 的地址,&b 表示变量 b 的地址。变量本身必须预先说明。

2:指针变量

既然&iNum是指向变量iNum的指针,那么存放指针&iNum的变量就是“指针变量”。从根本上来看,指针变量是一个值为内存地址的变量。如果有以下定义:

int iNum=0x64;

int *ptr =&iNum;

其中,“*”将变量声明为指针,这是一个重载过的符号。显然,重载就是为某个操作符定义新的含义,因为*用于乘法和间接访问或解引用指针时,其意义完全不一样。

iNum变量设置为0x64,在声明ptr的同时将它初始化为iNum的地址。当声明一个指针时,仅仅只是为指针本身分配了空间,并没有为指针所引用的数据分配空间。通常该声明被解读为ptr是指向int的变量iNum的指针,“int*”类型名被解读为指向int的变量iNum的指针类型。虽然ptr与&um的值相等,但它们的类型不一样。ptr的类型为int*,&iNum的类型为int*const即&iNum是一个指向非常量的常量指针,虽然指针不可变,但它所指向的数据可变。比如:

int iNum =0x64;

int const ptr=&iNum;

有了这个声明,则ptr必须被初始化为指向非常量变量,虽然不能修改ptr,但可以修改ptr指向的数据。如果试图初始化ptr使其指向常量Num,则ptr就成为了一个指向常量的指针,即不能通过指针修改它所引用的值。比如:

const int iNum =0x64;

int * const ptr = &iNum;

这样的话就会出现一个警告,因为常量不能被修改

虽然指针&iNum是指内存地址本身,指针变量ptr是指存储内存地址的变量,但两者之间的区别并不重要。因为传递一个指针变量给函数,其实就是在传递该指针的值一—内存地

址。通常在讨论一个内存地址时,将它称为地址;而在讨论一个存储内存地址的变量时,才会将它称为指针。当一个变量存储另一个变量的地址时,通常会说它指向了某个变量。

2.1:const关键字

无论怎样, const修饰的是紧跟在它后面的单词。比如,使用“const int a[2]={5,2};是将数组a的元素修饰为只读(它的值保持不变),而不是将变量a修饰为只读。注意,int const与 const int是等价的。既然可以用 const修饰变量,当然也可以用 const修饰指针变量。比如,“char* const src”是将src自身修饰为只读,而“const char* const src”是src和src指向的对象(变量的值)都修饰为只读。此外还有 const char*sc和 char const*src,其效果是一样的。注意,当指针作为传递参数时, const常用于将指针指向的对象设定为只读。注意,只读变量与指令一起保存在“只读段”中,而变量保存在“读写段”中。具有存储器保护功能的操作系统可能将只读段保护起来,不让程序修改值。类似 Cortex--M0+这样的MCU,其只读段与读写段是分别分配在 Flash与RAM中的,因此无法改变只读变量的值。由于 Flash比RAM便宜很多,且容量大很多,因此建议尽量将变量定义为只读变量,以达到节省存储空间的目的。

3:指针的指针

有如下定义:

int iNum =0x64;

int *ptr =&iNum;

当在“int*ptr;”定义前添加 typedef:

typedef int *ptr;

此时,ptr等同于int*。为了便于理解,通常将类型名ptr替换为ptiT比如:

typedef int *PTR_INT;

显然有了 PTR INT类型,即可构造指向 PTR INT类型的指针变量pPtr.即

PTR_INT *pPtr=&ptr;

其中,pPtr是指向PTRNT*的指针变量,PTR_INT的类型为int*,pPtr是指向int**的指针变量,那么pPtr就成了保存int型ptr地址的双重指针

其中,指针的类型为int**,指针指向的对象的类型为int*,只要看到*就应该想到指针变量。由于*的结合方式是从右到左的,该定义相当于:

int * *pPtr)=&ptr;

即*pPtr是一个一级指针变量。接着第一个*与(*ptr)结合成为“一级指针变量”,这同样是在定义一个指向指针类型数据的指针变量,即二级指针变量。在双重指针变量前,既可加一个或两个指针运算符*,也可以加取地址运算符&。则以

下关系恒成立:

*pPtr ==*(&ptr) == ptr == &iNum

**pPtr == *ptr == *(&iNum) == iNum

 

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值