指向数组的指针C语言

本文详细介绍了数组指针的概念,包括一维和二维数组指针的定义、使用方法及示例代码,帮助读者深入理解并掌握数组指针的应用。
指向数组的指针
指向数组的指针就是我们说的数组指针,假设它指向的数组为int型,那么它这样定义:int  (*p)[列数] ; 可数组有一维数组和二维数组之分,所以使用起来是不同的。下面就通过举栗子来说明一下两种数组指针的使用。
这里还有一个指针数组的概念简单给大家提一下,指针数组顾名思义是存放指针值的数组,它的定义:int  *p[元素个数] ; 可以看到两种定义非常相似,不同的就是差个( ),这是因为下标运算符[ ]的优先级非常高,p先与它结合,所以定义的是一个数组。今天在这里先不多介绍这个。下面步入正题,开始数组指针的说明:

一,指向一维数组的指针

其实一维数组指针的定义并不是上面说到的int  (*p)[列数] ; 这种定义主要是用在指向二维数组的指针的,那么一维数组指针怎样定义和使用呢:

我们先定义一个 int 型的一维数组:
int a[5]={1,2,3,4,5};

a是数组名,但同时它也是指向这个一维数组的指针,不过要注意的是,这是一个指针常量,用这个指针常量遍历数组时,如下面的伪代码:

for(int i=0;i<5;i++){ 数组元素:a[i]或是*(a+i)}

注意:因为a是一个指针常量,所以值不能改变。所以:
int a[5]={0,1,2,3,4},b[5]={5,6,7,8,9};
a=b;

这段代码会报错,因为你进行了改变一个常量的值的操作。
上面没有定义指针变量可以达到访问数组空间的目的,下面看一下指向一维数组的指针变量的定义和使用:
int a[5]={0,1,2,3,4};
int *p=a;
这样指针变量p就指向了数组a的空间,要遍历数组可以这样操作:
for(int i=0;i<5;i++)
{
	数组元素:p[i]或是*(p+i) 
}
这时p的值是可以改变的,
int a[5]={0,1,2,3,4},b[5]={5,6,7,8,9};
int *p=a;
p=b;

进行完上面的操作之后,p的指向由原来的指向a变成了现在的指向b。
再看一个需要我们注意的点:
int a[5]={0,1,2,3,4};
int *p=a;
printf("%d %d\n",sizeof(a),sizeof(p));

想一下输出结果是什么?一起来看:sizeof( )是用来计算空间所占字节数的。a是一个指针常量,它指向的空间数组a有5个占4字节的int型数值,所以它在内存中占用4*5=20个字节,而p是一个指针变量,它存的是一个指向 int 型空间的地址,本身只占4个字节,所以输出结果:20 4
上面我说道定义一位数组指针一般不用int  (*p)[列数] ; 其实也可以那样定义:
int a[5]={0,1,2,3,4};
int (*p)[5];
p=&a;

这样定义的话赋值就要用p=&a; 用p遍历时元素就是(*p)[i]
二,指向二维数组的指针
二维数组有行与列之分,指向二维数组的指针也就有行指针与列指针之分:

列指针用来指向二维数组的一个元素,定义:数据类型  * 列指针 ;
而行指针用来指向二维数组的一行,定义:数据类型  (*行指针)[列数] ;

使用如下:

int a[3][4]={1,2,3,4,10,20,30,40,100,200,300,400};
int *cp;		//列指针 
int (*rp)[4]; 	//行指针 
/*让rp指向第一行,让cp指向第一个元素*/
rp=a;
cp=*a;
注意:必须写cp=*a,因为cp是一个一级指针,而a是二维数组,写cp=a系统会报错,这里cp=*a也可以写成p=a[0]或p=&a[0][0],三条语句达到的效果是一样的。

这时如果要表示数组中某一个元素就会有许多种方式了:(以a[2][3]为例)
1,用行指针:(1). *(*(rp+2)+3) ; (2). (*(rp+2))[3] ; (3). rp[2][3] ;
2,用列指针:(1). *(cp+11) ; (2). cp[11] ; 

用二维数组指针遍历数组元素a[i][j]:

1,用列指针遍历:
  (1). 指针动:
for(i=0,cp=*a;i<行数*列数;i++,cp++)
	元素:*cp
  (2). 指针不动:
for(i=0,cp=*a;i<行数;i++)
	for(j=0;j<列数;j++)
		元素:*(cp+i*列数+j) 

2,用行指针遍历:
  (1). 指针动:
for(rp=a;rp<a+行数;rp++)
	for(j=0;j<列数;j++)
		元素:*(*rp+j) 

  (2). 指针不动:

for(i=0,rp=a;i<行数;i++)
	for(j=0;j<列数;j++)
		元素:*((*rp+i)+j) 即 rp[i][j] 
3,组合遍历:
for(rp=a;rp<a+行数;rp++)
	for(cp=*rp;cp<*rp+列数;cp++)
		元素:*cp 

总结一下其实并不复杂,只是在进行每一步操作时要注意类型匹配:在上例中,cp是int    *类型,那么*cp是int型,rp是int *[ ]类型,*rp是int *类型,**rp是int型。可以看到cp只有一级指向,而rp有两级指向。
再理一理上面例子中a+i,a[i],*(a+i)的关系:a是二维数组名,它其实就是a+0,它影射的单元是二维数组a的第一行,所以a+i所影射的就是数组的第i行,行指针rp和它是一样的道理了,所以rp++就是沿垂直方向走到数组的下一行。而a[i]与*(a+i)是等价的,它们影射的单元都是数组的一个元素,同样的,列指针cp和它们也是一样的道理,所以cp++就是沿水平方向走到数组的下一列就是下一个元素。
接下来试做一个简单的例题:按行输出二维数组每行的最大值,要求用指针操作

(1).

#include <stdio.h> int main() {     int a[3][4]={{1,2,3,4},{10,20,30,40},{100,200,300,400}};     int (*rp)[4];//行指针     int *cp;//列指针     cp=a[0];rp=a;//cp=*a;cp=&a[0][0];     int max=*cp,i,j,k;     for(k=0;k<3;k++)     {
for(i=0;i<4;i++,cp++)          if(max<*cp) max=*cp; printf("%d ",max);     }
    printf("\n"); }
(2).
#include <stdio.h> int main() { int a[3][4]={{1,2,3,4},{10,20,30,40},{100,200,300,400}}; int (*rp)[4];//行指针 int *cp;//列指针 cp=a[0];rp=a;//cp=*a;cp=&a[0][0]; int max=*cp,i,j,k; for(i=0;i<3;i++)         {              for(j=0;j<4;j++)                   if(max<*(cp+4*i+j))                        max=*(cp+4*i+j);              printf("%d ",max);         }
        printf("\n");
}
(3).
#include <stdio.h> int main() { int a[3][4]={{1,2,3,4},{10,20,30,40},{100,200,300,400}}; int (*rp)[4];//行指针 int *cp;//列指针 cp=a[0];rp=a;//cp=*a;cp=&a[0][0]; int max=*cp,i,j,k; for(i=0;i<3;i++)         {              for(j=0;j<4;j++)                   if(max<*(*(rp+i)+j))                        max=*(*(rp+i)+j);              printf("%d ",max);         }
        printf("\n");
}
(4).
#include <stdio.h> int main() { int a[3][4]={{1,2,3,4},{10,20,30,40},{100,200,300,400}}; int (*rp)[4];//行指针 int *cp;//列指针 cp=a[0];rp=a;//cp=*a;cp=&a[0][0]; int max=*cp,i,j,k; for(;rp<a+3;rp++)         {              for(j=0;j<4;j++)                   if(max<*(*rp+j))                        max=*(*rp+j);              printf("%d ",max);         }
        printf("\n");
}
(5).
#include <stdio.h> int main() { int a[3][4]={{1,2,3,4},{10,20,30,40},{100,200,300,400}}; int (*rp)[4];//行指针 int *cp;//列指针 cp=a[0];rp=a;//cp=*a;cp=&a[0][0]; int max=*cp,i,j,k; for(rp=a;rp<a+3;rp++)         {              for(cp=*rp;cp<*rp+4;cp++)                   if(max<*cp)                        max=*cp;              printf("%d ",max);         }
        printf("\n");
}
输出结果:4 40 400


<think>好的,用户想了解C语言指向数组指针的用法和示例。首先,我需要回忆一下C语言指针数组的关系。指向数组指针其实通常是指向数组首元素的指针,或者是数组指针,即指向整个数组指针。这两者有些区别,需要分清楚。 根据引用[4],数组名在大多数情况下会被转换为指向其首元素的指针。例如,int arr[4]中,arr通常被当作int*类型。但有时候,比如使用sizeof(arr),数组名代表整个数组。所以,这里可能需要解释两种不同的指针类型:指向数组元素的指针指向整个数组指针。 接下来,用户需要具体的用法和示例。首先,指向数组元素的指针比较简单,声明为int* ptr = arr;,然后通过ptr[i]或者*(ptr + i)访问元素。但如果是数组指针,即指向整个数组指针,声明应该是int (*ptr)[n] = &arr;,这样ptr指向的是整个数组,步长是整个数组的大小,这在多维数组中有用,比如处理二维数组时。 引用[2]提到了指向指针指针在动态分配二维数组中的应用,这可能和数组指针相关。比如,使用int (*matrix)[3]来声明一个指向包含3个元素的数组指针,这样分配内存时可以更方便地处理二维数组。 此外,引用[5]指出结构体作为参数传递时,使用指针更高效。类似地,传递数组时,使用指针可以避免复制整个数组,提高效率。所以在函数参数中使用数组指针也是一个重要应用场景。 需要区分指针数组数组指针指针数组数组元素为指针,而数组指针指针指向整个数组。用户可能容易混淆这两者,所以需要明确说明。 然后,我应该给出具体示例。例如,指向一维数组元素的指针指向整个一维数组指针的不同声明和使用方式。对于二维数组数组指针可以用来处理行指针,比如int (*ptr)[3]指向二维数组的每一行。 另外,动态分配内存的情况,比如用malloc分配一个二维数组,使用数组指针可以更方便地进行访问和释放。这部分可能需要结合引用[2]中的示例,但需要调整为数组指针的形式。 需要注意语法问题,比如括号的位置,int (*ptr)[n]和int* ptr[n]的区别。同时,在示例代码中,要正确使用指针访问数组元素,比如使用(*ptr)[i]或者ptr[0][i]的方式。 可能还需要提到数组作为函数参数时,会自动退化为指针,所以函数接收时可以用指针形式,但如果是数组指针,则需要明确声明维度,以保持类型安全。 最后,总结使用场景,比如函数参数传递、动态多维数组处理等,帮助用户理解何时使用数组指针。同时,注意常见错误,比如指针类型不匹配导致的越界或未定义行为,结合引用[3]中提到的指针常见错误,提醒用户注意正确声明和使用。</think>### C语言指向数组指针使用方法及示例 #### 一、指向数组指针定义 指向数组指针分为两种类型: 1. **指向数组元素的指针**:声明为元素类型指针(如 `int*`),用于逐个访问数组元素。 2. **指向整个数组指针**:声明为数组指针(如 `int (*)[N]`),用于操作整个数组或作为多维数组的行指针。 --- #### 二、使用方法 1. **指向数组元素的指针** ```c int arr[5] = {1, 2, 3, 4, 5}; int *ptr = arr; // ptr指向数组首元素 ``` - 通过指针访问元素: ```c printf("%d", *ptr); // 输出第一个元素 printf("%d", *(ptr+2));// 输出第三个元素 ``` 2. **指向整个数组指针** ```c int arr[3] = {10, 20, 30}; int (*ptr)[3] = &arr; // ptr指向整个数组 ``` - 通过指针访问数组: ```c printf("%d", (*ptr)[1]); // 输出第二个元素 ``` 3. **在函数参数中传递数组指针** ```c void print_array(int (*p)[3]) { for (int i = 0; i < 3; i++) printf("%d ", (*p)[i]); } ``` --- #### 三、示例代码 1. **一维数组指针操作** ```c #include <stdio.h> int main() { int arr[] = {1, 3, 5, 7, 9}; int *p = arr; // 指向首元素的指针 for (int i = 0; i < 5; i++) { printf("%d ", *(p + i)); // 输出:1 3 5 7 9 } return 0; } ``` 2. **二维数组与行指针** ```c #include <stdio.h> int main() { int matrix[2][3] = {{1,2,3}, {4,5,6}}; int (*p)[3] = matrix; // 行指针指向二维数组的每一行 for (int i = 0; i < 2; i++) { for (int j = 0; j < 3; j++) { printf("%d ", p[i][j]); // 输出:1 2 3 4 5 6 } } return 0; } ``` 3. **动态分配二维数组** ```c #include <stdio.h> #include <stdlib.h> int main() { int rows = 2, cols = 3; int (*dynamic_matrix)[cols] = malloc(rows * sizeof(*dynamic_matrix)); // 分配2x3数组 for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { dynamic_matrix[i][j] = i * cols + j + 1; } } free(dynamic_matrix); return 0; } ``` --- #### 四、关键注意事项 1. **指针类型匹配**:指向整个数组指针类型需严格匹配数组维度,如 `int (*)[3]` 只能指向长度为3的数组[^4]。 2. **避免越界访问**:指针操作需确保不超出数组边界,否则会导致未定义行为[^3]。 3. **函数参数传递**:传递数组指针时,函数参数需明确维度(如 `void func(int (*p)[3])`),以保持类型安全[^5]。 --- #### 五、应用场景 1. **高效传递多维数组**:通过行指针传递二维数组,避免数据拷贝[^2]。 2. **动态内存管理**:结合 `malloc` 分配动态多维数组。 3. **类型安全的操作**:通过数组指针限制操作范围,减少逻辑错误[^5]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值