C语言指针理解

C语言指针学习笔记

参考:http://c.biancheng.net/c/pointer/

指针的定义:指针提供了对地址操作的一种方法,因此,使用指针可以使得C语言能够更高效地实现对计算机底层硬件的操作;另外,通过指针可以更便捷地操作数组。在一定意义上,指针是C语言的精髓所在

内存与地址

  1. 在计算机中,数据是存放在内存单元中的,一般把内存中的一个字节称为一个内存单元;在内存中,为了更方便的访问这些内存单元,可以给每一个内存单元进行地址编号。每一个地址编号对应一个内存单元,或者说一个地址编号就对应一个内存单元。C语言中把地址形象的称作指针*
  2. 在C语言中,可以使用&符号得到某个变量的地址
    • 例如:int a = 10; &a即可得到变量a在内存中的地址
  3. 在C语言中,char型变量占一个字节的内存空间,而整型占用的空间大小和系统有关
    • 每个地址编号对应字节单元的起始地址
    • 例如:int a = 100; char c = ‘A’;在内存中的分布情况
      [外链图片转存失败(img-eVcaYmfh-1566195872009)(CPointExp.jpg)]
      由上图可知,变量 a 对应于从地址 12ff40 开始的 4 个字节(12ff40、12ff41、12ff42、12ff43)的内存空间,存储的是整数 100 的 32 位二进制形式(为直观表示,本例并没有转换成二进制形式)。字符型变量 c,对应地址为 12ff44,该地址内存储的是字母对应 ASCII 值的 8 位二进制形式。
      • 语句 printf(“a=%d\n”,a); 输出:a=100。
      • 语句 printf("&a=%x\n",&a); 是按十六进制形式输出变量 a 的地址(a 在内存中的起始地址值)为 &a=12ff40。
      • 在上例中,变量 a 和 c 的起始地址 12ff40 和 12ff44 均为指针,分别指向变量 a 和变量 c。
      • 区分变量的地址值和变量的值。如上例中,变量 a 的地址值(指针值)为12ff40,而变量 a 的值为 100。

指针变量的定义

######. 可以保存地址值(指针)的变量称为指针变量,因为指针变量中保存的是地址值,故可以把指针变量形象地比喻成地址箱。
指针变量的定义形式如下。
类型 * 变量名;
例如:nt *pa; 定义了一个整型指针变量 pa,该指针变量只能指向基类型为 int 的整型变量,即只能保存整型变量的地址。
说明:
1. *号标识该变量为指针类型,当定义多个指针变量时,在每个指针变量名前面均需要加一个 *,不能省略,否则为非指针变量。例如:int *pa, *pb;表示定义了两个指针变量 pa、pb。而: int *pa,pb; 则仅有 pa 是指针变量,而 pb 是整型变量。
2. 在使用已定义好的指针变量时,在变量名前面不能加 *。例如:
int *p,a;
p = &a; //错误,指针变量是p而不是p
p = &a; //正确
3. 类型为该指针变量所指向的基类型,可以为 int、char、float 等基本数据类型,也可以为自定义数据类型。该指针变量中只能保存该基类型变量的地址。
4. 变量名是一合法标识符,为与普通变量相区分,一般指针变量名以字母 p(pointer)开头,如 pa、pb 等。
5. 由于是变量,故指针变量的值可以改变,也即可以改变指针变量的指向。
6. 同类型的指针变量可以相互赋值。

指针变量的引用

访问内存空间,一般分为直接访问和间接访问。
  • 如果知道内存空间的名字,可通过名字访问该空间,称为直接访问
  • 如果知道内存空间的地址,也可以通过该地址间接访问该空间
  • 对内存空间的访问操作一般指的是存、取操作,即向内存空间中存入数据和从内存空间中读取数据
  • 在 C 语言中,可以使用间接访问符(取内容访问符)*来访问指针所指向的空间
  • 例如:

    int *p,a=3;//p中保存变量a对应内存单元的地址
    p=&a;
    printf(“a=%d\n”,a); //通过名字,直接访问变量a空间(读取)
    printf(“a=%d\n”,*p); //通过地址,间接访问变量a空间(读取)
    *p=6;//等价于a=6;间接访问a对应空间(存)

“野”指针

  • 把没有合法指向的指针称为“野”指针。因为“野”指针随机指向一块空间,该空间中存储的可能是其他程序的数据甚至是系统数据,故不能对“野”指针所指向的空间进行存取操作,否则轻者会引起程序崩溃,严重的可能导致整个系统崩溃。

指针与数组

  • 在 C 语言中,指针变量加 1 表示跳过该指针变量对应的基类型所占字节数大小的空间。指向数组元素的指针,其基类型为数组元素类型,指针加 1 表示跳过一个数组元素空间,指向下一个数组元素。
  • 数组名相当于数组首元素的地址,即:

    int *p, a[10];
    p = a; //相当于 p=&a[0];a 等价于 &a[0]

  • 数组的访问方式:
    1. 直接访问:数组名[下标]; 的形式。如 a[3]。
    2. 间接访问:*(数组名+i); 的形式。其中,i 为整数,其范围为:0<i<N,N 为数组大小。数组名 a 为首元素的地址,是地址常量,a+i 表示跳过 i 个数据元素的存储空间,即(a+i)表示 a[i] 元素的地址,从而 *(a+i) 表示 a[i]。
    3. 如果指针变量 p 被初始化为 a 之后,不再改变,那么也可以使用 *(p + i) 的形式访问 a[i],不过这样就失去了使用指针变量访问数组元素的意义。
    4. 间接访问:*(指针变量);的形式。当执行语句 p=a; 后,可以通过改变 p 自身的值(可通过自增、自减运算),从而使得 p 中保存不同的数组元素的地址,进而通过 *p 访问该数组中不同的元素。这是使用指针访问数组元素较常用的形式。
  • 指针值加 1 与地址值加 1 的区别如下。
    • 一般地址单元也称内存单元,是按字节划分的,即地址值加 1,表示跳过一个字节的内存空间。
    • 在 C 语言中,指针变量加 1 表示跳过该指针变量对应基类型所占字节数大小的空间。
    • 在 VC++ 6.0 中,整型占 4 个字节,故对于整型指针变量来说,指针值加 1 对应地址值加 4,即跳过 4 个字节;字符型占 1 个字节,故字符型指针变量加 1,对应地址值也加 1,即跳过 1 个字节。double 型占 8 个字节,故 double 型指针变量加 1,对应地址值加 8,即跳过 8 个字节等。

二维数组与指针

  • 二维数组的逻辑结构为行列形式,但二维数组的存储结构为顺序形式。即二维数组中的数据元素在内存中的存储地址是连续的,故可以使用指针变量保存各个元素的地址值,进而可以间接访问二维数组中的各元素。
  • M 行 N 列的二维数组 a,可以看成是含有 a[0]、a[1]、…、a[M-1] 等 M 个元素(M 行)的特殊一维数组,其每个元素 a[i](每行)又是一个含有 N 个元素(N 列)的一维数组。

数组指针与指针数组

数组指针

数组指针: 数组指针,即指向一维数组的指针。
数组指针的定义格式为: 类型 (*指针名)[N]; //N元素个数

指针数组

指针数组,即存储指针的数组,数组中的每个元素均是同类型的指针。
指针数组的定义格式为: 类型 *数组名[数组大小];

指针与字符串

  • 字符串常量

    字符串常量返回的是一个字符指针常量,该字符指针常量中保存的是该字符串首字符的地址,即指向字符串中第一个字符的指针。

  • 字符串变量

    字符数组可以理解为若干个字符变量的集合,如果一个字符串存放在字符数组中,那么字符串中的每个字符都相当于变量,故该字符串中的每个字符均可以改变,故可把存放在字符数组中的字符串称为变量字符串。

指针与函数

  • 指针作函教形参——传址调用
  • 指针作函教返回类型——指针函教
  • 指向函教的指针——函教指针
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值