C语言指针与数组

指针与数组

指向数组元素的指针

//定义a为包含10个整型数据的数组
int a[] = {1,3,5,7,9,13,15,17,19};  
int *p;     //定义P为指向整型变量的指针变量   
p = &a[3];  //把a[3]元素的地址赋给指针变量p
//*p 等价于 a[3]

指向复合字面量的指针

复合字面量是C99的一个特性,可以用于创建没有名称的数组。

int* p = (int []){1,3,5,7,9,13,15,17,19};  

指针的算数运算

指针加上或减去整数

如果指针变量 p 指向数组元素a[i],那么p+j就指向了a[i+j]
如果指针变量 p 指向数组元素a[i],那么p-j就指向了a[i-j]

int a[9] = {1,3,5,7,9,13,15,17,19}; 
int* p = &a[5];  //*p = 13 
printf( "%d\n", *(p - 2) ); //*(p - 2) = 7 
printf( "%d\n", *(p + 2) ); //*(p + 2) = 17 

两个指针变量可以相减

如果两个指针变量指向指向同一个数组的元素,则两个指针变量值的差是两个指针之间的距离。
即,如果 p 指向a[i] 且 q 指向a[j],那么p-q就等于i-j

int a[9] = { 1,3,5,7,9,13,15,17,19 };
int* p = &a[5];  //*p = 13 
int* q = &a[2];  //*q = 5
printf( "%d\n", a[p - q] );//a[3] = 7,p-q 相当于 5-2

两个指针变量可以比较

如果两个指针变量指向指向同一个数组的元素,则可以进行比较;指向前面元素的指针变量小于指向后面元素的指针变量。

使用指针遍历数组

int a[9] = { 1,3,5,7,9,13,15,17,19 };
for (int* p = a;  p < a + 9; p++)
{
    printf("%d ",*p);
}

解引用和递增运算符的组合

在一条语句中混用解引用*和后置递增运算符++

int a[] = {1,2,3,4,5};
int *p = a;
/* 输出当前值,并将指针向前移动一个元素 */ printf("%d\n",*p++); 

后置递增运算符优先级高于解引用运算符,因此 *p++ 等价于 *(p++)
在一条语句中混用解引用*和前置递增运算符++

int a[] = {1,2,3,4,5};
int *p = a;
/* 将指针向前移动一个元素,然后输出移动后的值 */ 
printf("%d\n", *++p);
表达式含义
*p++自增前表达式的值是 *p,然后再自增 p
(*p)++自增前表达式的值是 *p,然后再自增 *p
*++p先自增 p,自增后表达式的值是 *p
++*p先自增 *p,自增后表达式的值是 *p

用数组名作指针

数组名代表数组的首元素的地址,也就是第0号元素的地址。
数组名是常量,不能给数组名赋新值。
C语言允许把数组名看作指针进行取指针运算。
C语言允许把指针看作数组名进行取下标操作。
如果指针变量 p 的初值为数组名 a,则:

  1. p+ia+i就是 a[i] 的地址,即它们指向数组 a 的第 i 个元素。
  2. *(p+i)*(a+i) 就是p+ia+i所指向的数组元素,即 a[i]
  3. 指向数组元素的指针也可以带下标,即 p[i]*(p+i) 等价。

数组名作函数实参

用数组名做函数的实参,传递的是数组首元素的地址。
C编译系统将形参数组名一律作为指针变量来处理。

//形参,声明arr是指针就相当于声明它是数组。
fun(int *arr,int n); 等价于 fun(int arr[],int n); 
//实参,array为数组名,代表一个固定地址,指针型常量,不能改变其值。
fun(array,n); //函数调用

说明:

  1. 如果函数实参是数组名,形参可以是数组名也可以是指针变量。
  2. 实参数组和形参数组应类型一致。
  3. 实参数组名代表一个固定的地址,但形参数组名并不是一个固定的地址,而是按指针变量处理。
  4. 用数组名作函数实参,在函数调用后,形参的值就是实参数组首元素的地址。
  5. 用数组名作函数实参时,如果改变了形参数组元素的值将同时改变实参数组元素的值。

指针和多维数组

处理多维数组的元素

通过下标遍历数组元素
 int arr[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} };
for (int row = 0; row < 3; row++) //打印行
{
    for (int col = 0; col < 4; col++) //打印列
    {
        printf("%d ",arr[row][col]);
    }
    printf("\n");
}
通过指针遍历数组元素
int arr[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} };
for (int* p = &arr[0][0]; p <= &arr[2][3]; p++)
{
    printf("%d ", *p);
}

处理多维数组的行

int arr[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} };
/*遍历数组的第 1 行*/
for (int* p = arr[1]; p < &arr[1][4]; p++)
{
	printf("%d ", *p);
}

处理多维数组的列

int arr[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} };
/*遍历数组的第 3 列*/
for (int (*p)[4] = &arr[0]; p < &arr[3]; p++)
{
    printf("%d ", (*p)[3] );
}
  • int (*p)[4]表示 p 是int型指针,(*p)有 4 个元素,每个元素为整型。
  • &arr[0]代表 p 指向 arr 首行,类型是int (*)[4]
  • p++把 p 移到下一行的开始位置。
  • *p代表 arr 的一整行。
  • (*p)[3]选中了改行的第 3 列元素。
  • 14
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

往昔的恒纳兰那

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值