函数、数组、指针的结合

1、数组与指针的结合使用

数组名是数组首地址,是一个指针常量,如 int a[10],关系上:a == &a[0],对于二维数组,也有类似的关系,如 int a[2][4],其中 &a[0][0] 、 a 、 &a[0] 、a[0] 在数值上是相等的,都表示首地址,在关系上:a==&a[0] ;a[0]=&a[0][0] ;a[1]=&a[1][0];可参考下面代码的执行结果:

#include<stdio.h>
int main(void)
{
		int a[2][4];
		printf("%p\n",a);
		printf("%p\n",a[0]);
		printf("%p\n",&a[0]);
		printf("%p\n",&a[0][0]);
		return 0;
}

 ./test
0x7fff647ba190
0x7fff647ba190
0x7fff647ba190
0x7fff647ba190

然后再来看一段代码:


 #include <stdio.h> 
 int main(void) {
       int a[10]={1,2,3,4,5,6,7,8,9,0};
   
       int *p=a;
       printf("%d\n",a[5]);
       printf("%d\n",p[5]);
       printf("%d\n",*(a+5));         //*(a++) 错误
       printf("%d\n",*(p++));        //p++次改的指针p的值   p+1只是使用了指针并没有修改指针
       printf("%d\n",*(p+1));
   
       return 0; }
执行:
./test
6
6
6
1
3

在代码中,p存放的是一维数组 a[10] 的首地址,按照执行逻辑来推算结果:重点看后两行,*(p++),按照运算,应该是先进行取值p,即 *p,所以 *(p++)等于1,之后再执行自加,p存储的地址自加后得到的应该是a[2]的地址,所以 *(p+1)= *(&a[2]+1)= *( &a[3] ) = a[3]。

再看二维数组与指针,参考下面这段代码

#include <stdio.h>
int main(void)
{
    int a[2][4]={1,2,3,4,5,6,7,8};

    int (*p)[4];
    p=a;

    printf("%d\n",a[1][2]);
    printf("%d\n",p[1][2]);
    printf("%d\n",*(*(a+1)+2));
    printf("%d\n",*(*(p+1)+2));

    return 0;
}
执行:
./test
7
7
7
7

首先分析(*p)[4] 是什么,按照运算符优先级,()与[ ] 都是一级运算符,但遵循从左到右的运算顺序,所以(*p)[4] 代表的是数组指针,本质上是一个指针,指向的是int [4]类型,即一维数组的地址,然而二维数组本质上是由两个一维数组组成的,所以该数组指针保存的的应该是第一个一维数组的首地址,即&a[0][0],另外,在二维数组中,a=&a[0]、a[0]=&a[0][0],所以由此:
*( *(p+1)+2)= * ( * (&a[0]+1)+2) = * (&a[1]+2) = * (&a[1][0]+2)=a[1][2],同时进行总结

int (*p)[4]=a; //数组指针 :本质上是一个指针,保存int [4]类型(即一维数组类型)的地址.
int * p[4]; //指针数组 :本质上是一个数组,数组有4个成员,这4个成员都是int *

--------------------------------------------分割线--------------------------------------------------------------------------

2、指针与函数的结合使用
大部分是指针作为函数的形参,用于址传递

址传递:传地址 修改形参能改变对应实参

#include <stdio.h>
void swap(int *a,int *b)
{
    int temp;
    temp=*a;
    *a=*b;
    *b=temp;

}
int main(void)
{
    int a,b;
    scanf("%d%d",&a,&b);
    swap(&a,&b);
    printf("%d %d\n",a,b);
    return 0;
}
执行:
./test
输入:1 2
输出:2 1

值传递:传数值 修改形参不能改变对应实参

#include <stdio.h>
void fun(int *p)
{
    int b=20;
    p=&b;
    *p=50;
}

int main(void)
{
    int a=10;
    fun(&a);
    printf("%d\n",a);
    return 0;
}
执行:
./test
输入:10
输出:10

再看一个例子

例:封装函数,求两个数的和与差

#include <stdio.h>

void fun(int c,int d,int *p,int *q)        //因为指针做形参,修改形参的值能够改变实参的值    利用这个特点,实现函数把多个数据传出去
{
    *p=c+d;
    *q=c-d;

}

int main(void)
{
    int a,b;
    scanf("%d%d",&a,&b);

    int sum,sub;
    fun(a,b,&sum,&sub);
    
    printf("%d %d\n",sum,sub);
    return 0;
}

数组与函数的结合:
把数组传到自定义函数中进行操作。数组名做实参.
一维数组名做实参,形参有三种写法: int *p , int p[10] , int p[ ]
//这三种写法只是形式不同,本质上都理解为指针int *p的形式
二维数组名做实参,形参有三种写法: int (*p)[4] , int p[2][4] , int p[ ][4]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值