C语言基础知识整理14指针妙用

本文详细介绍了C语言中指针如何作为函数参数来引用和操作数组,包括数组元素的指针、引用数组元素、通过指针引用数组和字符串的方法。通过指针可以改变函数外变量的值,实现数据的传递和更新,同时讲解了指针在引用多维数组和字符串中的使用技巧,以及与字符数组的区别和联系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

指针变量作函数参数

函数参数可以是指针类型,作用是将一个变量的地址传送到另一个函数中。

为使在函数中改变的变量值能被主调函数main使用,应用指针变量作为函数参数,在函数执行过程中使指针变量所指向的变量值发生变化,函数调用结束后,这些变量值的变化依然保留下来,这样就实现了“通过调用函数使变量的值发生变化,在主调函数中可以使用这些改变了的值”的目的。

若想通过函数调用得到n个要改变的值,可以如此:

  1. 在主调函数中设n个变量,用n个指针变量指向它们;
  2. 设计一个函数,有n个指针形参。在函数中改变这n个形参的值;
  3. 在主调函数中调用这个函数,将这n个指针变量作实参,将其地址传给函数形参;
  4. 执行函数过程中,通过形参改变它们所指向的n个变量的值;
  5. 主调函数就可以使用这些改变了值的变量。

注意:不能企图通过改变指针形参的值而使其指针实参的值改变

函数调用可以(而且只可以)得到一个返回值(函数值),而使用指针变量作参数,可以得到多个变化了的值要善于利用指针法

通过指针引用数组

数组元素的指针

数组元素的指针就是数组元素的地址

可以用一个指针变量指向一个数组元素。

在C中,数组名(不包括形参数组名,形参数组不占据实际的内存地址)代表数组中首元素(即序号为0的元素)的地址。因此p=&a[0];等价于p=a;

数组名不代表整个数组,只代表数组首元素的地址。“p=a;”作用是把a数组的首元素的地址赋给指针变量p,而不是把数组a各元素的值赋给p。

定义时初始化:int *p=&a[0];等价于int a;p=&a[0];等价于int *p=a;

作用是将a数组的首元素(a[0])的地址赋给指针变量p(而不是赋给*p)。

引用数组元素时指针的运算

在一定条件下(当指针指向数组元素的时候)允许对指针进行加和减的运算。如:

1.加/减一个整数(用+/-或+=/-=),如p+1/p-1;

若指针变量p指向数组中某元素,则p+1/p-1指向下/上一个元素。注意:p+1加的是一个数组元素所占用的字节数。p+1所代表的地址实际上是p+1*dd为一个数组元素所占的字节数。

p初值为&a[0],则p+ia+i就是数组元素a[i]的地址,或者说,它们指向a数组序号为i的元素。//a代表数组首元素地址,a+i也是地址。计算方法和p+i一致。

*p+i*a+i是p+i或a+i所指向的数组元素,即a[i]

在编译时,对数组元素a[i]按*(a+i)处理,即按照数组首元素地址加上相对应移量得到要找的元素的地址,然后找出该单元中的内容。

[]实际上是变址运算符,即将a[i]按a+i计算地址,然后找出该地址单元中的值。

2.自加/减运算,如p++,++p/p--,--p;

3.两个指针相减,如p1-p2(只有p1和p2都指向同一数组中的元素时才有意义)。两个地址相加没有意义

如果指针变量p1和p2都指向同一个数组,则p2-p1结果是p2-p1的值(两个地址之差)除以数组元素的长度。表示两个数组元素之间相差的元素个数(相对距离)。

通过指针引用数组元素

方法:

  1. 下标法:如a[i]形式;
  2. 指针法:如*(a+i)或*(p+i)。其中a是数组名,p是指向数组元素的指针变量,其初值p=a。

方法比较:

1.用下标法和*(a+i)效率一致,C编译系统将a[i]转换为*(a+i)处理,即先计算元素地址。因此这两个方法找数组元素费时较多;

2.用*(p+i)最快,简洁高效。用指针变量直接指向元素,不必每次都重新计算地址,像p++这种有规律地改变地址值能大大提高执行效率;

3.而用下标法比较直观,不易出错,能直接知道是第几个元素。用地址法和指针变量没有这么直观。

注意:可以通过改变指针变量的值指向不同的元素。但是不能改变数组名a的值(如a++是不行的),数组名代表数组首元素的地址,是一个指针型常量,其值在程序运行期间是固定不变的。  

注意:改变指针变量值的过程中要注意指针变量的当前值。应切实保证指向数组中有效的元素。

当指针变量指向数组元素时,指针变量可以带下标。在程序编译时,下标会转换为地址,对p[i]处理成*(p+i)。即当前元素基础上加i个元素。建议少用,容易出错

小技巧:

*p++等同于*(p++)相当于a[i++]:先引用p的值,实现*p的运算,然后使p自增1。

*(++p)相当于a[++i]:先使p自加,再取*p。

++(*p)相当于++a[i]:表示p所指向的元素值+1。

用数组名作函数参数

C编译将形参数组名作为指针变量处理。//常用此方法调用函数改变实参数组的值。

void fun(int arr[ ]);等价于void fun(int *arr);

以变量名和数组名作函数参数的比较

实参类型

变量名

数组名

要求形参的类型

变量名

数组名或指针变量

传递的信息

变量的值

实参数组首元素的地址

通过函数调用能否改变实参的值

不能改变实参变量的值

能改变实参数组的值

C调用函数皆以“值传递”方式,用变量名时传递的是变量的值,用数组名时传递的值为地址,因此要求形参为指针变量。

在C语言中下标法与指针法都可以访问同一数组,因此可以用数组名或者指针变量作实参或形参。

注意:实参数组名代表一个固定地址,或者说是指针常量,但形参数组名并非一个固定地址,而是按指针变量处理

若有一个实参数组,要想在函数中改变此数组中的元素的值,实参与形参的对应关系有以下四种://这四种方法,实际上都是地址的传递。实际上形参都是使用指针变量。

  1. 实参形参都用数组名;
  2. 实参用数组名,形参用指针变量;
  3. 实参形参都用指针变量;
  4. 实参用指针变量,形参用数组名。

//若用指针变量作实参,必须先使指针变量有确定值,指向一个已定义的对象。

通过指针引用多维数组类型名(*指针变量名)[m];

多维数组元素地址

指针可以指向一维数组中的元素,也可以指向多维数组中的元素。

a[i]从形式上看是a数组中序号为i的元素。若a是一维数组名,则a[i]代表a数组序号为i的元素的存储单元。a[i]是有物理地址的,是占存储单元的。但若a是二维数组,则a[i]是一维数组名,它只是一个地址,并不代表某一元素的值(如同一维数组名只是一个指针常量一样)。

二维数组a的有关指针

表示形式

含义

地址

a

二维数组名,指向一维数组a[0],即0行首地址

2000

a[0],*(a+0),*a

0行0列元素地址

2000

a+1,&a[1]

1行首地址

2016

a[1],*(a+1)

1行0列元素a[1][0]的地址

2016

a[1]+2,*(a+1)+2,&a[1][2]

1行2列元素a[1][2]的地址

2024

*(a[1]+2),*(*(a+1)+2),a[1][2]

1行2列元素a[1][2]的值

元素值3

*a[i]+j**a+i+j)与a[i][j]等价      *a+i)与a[i]等价

//a[0],a[1],a[i]的类型为int *型,指向整型变量,而a的类型为int(*)[4],指向含4个元素的一维数组。

//二维数组名是指向行的,一维数组名是指向列的。

//在指向行的指针前面加一个*,就转换为指向列的指针。 行a或a+1      列*a或*(a+1)

//在指向列的指针前面加一个&,就成为指向行的指针。。    列a[0]        行&a[0]

指向多维数组元素的指针变量

1.指向数组元素的指针变量:类型名 * 指针变量名;

数组元素a[i][j]相对位置计算公式:i*m+j//m为二维数组列数

若开始指针变量p指向a[0][0],则a[i][j]的地址为“&a[i][j]+(i*m+j)”或“p+(i*m+j)”

//C下标从0开始,对计算相对位置比较方便。

2.指向由m个元素组成的一维数组的指针变量:类型名(*指针变量名)[m];

//定义时的()不可少//指针类型为  类型名(*)[m]型

//此时指针指向一个包含m个元素的一维数组。指针的值就是该一维数组的起始地址。

3.用指向数组的指针作函数参数

//一维数组名可以作为函数参数,多维数组名也可以。

//用指针变量作形参,以接受实参数组名传递来的地址。可以有两种方法:

//1.用指向变量的指针变量;//2.用指向一维数组的指针变量。

通过指针引用字符串

字符串引用方式

在C程序中,字符串是存放在字符数组中的。引用的方式有:

  1. 字符数组存放字符串,可通过数组名和下标引用其中一个字符,也可通过数组名和格式声明“%s”输出该字符串。
  2. 字符指针变量指向一个字符串常量,通过字符指针变量引用字符串常量。

如:char *string=“I love China!”;等价于char *string;string=“I love China!”;

//对字符指针变量string初始化,实际上是把字符串第一个元素的地址(即存放字符串的字符数组的首元素地址)赋给指针变量string,使string指向字符串的第1个字符。

//内存中字符串最后被自动加了一个’\0’。因此能用%s输出,%s逐个输出字符直到’\0’停止

字符指针作函数参数

若想把一个字符串从一个函数“传递”到另一个函数,可以用地址传递的办法,即用字符数组名作参数,也可以用字符指针变量作参数。效果一致。

函数的形参实参可以用字符数组名或字符指针变量。

调用函数时实参与形参的对应关系

实参

形参

实参

形参

字符数组名

字符数组名

字符指针变量

字符指针变量

字符数组名

字符指针变量

字符指针变量

字符数组名

使用字符指针变量和字符数组的比较

(1)数组放字符,指针放地址;

(2)指针可赋值,数组名不行;

(3)初始化含义,一个地址,一个值char *a="I love";等价于char *[a];  a="I love";

char str[14]="I love";不等价于char str[14];str="I love";

//出错,数组只能定义时候赋初值,而不能用赋值语句进行赋值

(4)存储单元内容,数组分配若干个,指针分配一个;

(5)指针变量值可以改变,数组名的值是固定的;

(6)数组中各元素值可以改变,字符指针指向的字符串常量中的内容不可改变

      char a[]="House";char *b="House";

      a[2]='r';合法        b[2]='r';不合法,字符串常量不能改变

(7)引用数组元素。字符数组用下标法/地址法。而指针需要先指向数组才可引用

(8)用指针变量指向一个格式字符串,可以用它代替printf函数中的格式字符串。(可变格式输出函数)

     char *i;i="a=%d,b=%d\n";printf(i,a,b);相当于printf("a=%d,b=%d\n",a,b);

     也可使用字符数组实现:char i[]="a=%d,b=%d\n";   指针更为方便,从赋值角度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值