指针进阶 - 2(数组参数和指针参数)

简介: 指针进阶 - 2(数组参数和指针参数)

在写代码的时候难免要把【数组】或者【指针】传给函数,那函数的参数该如何设计呢?

1. 一维数组传参

一维数组传参指的是将一个一维数组作为参数传递给一个函数。

在C/C++中,可以使用以下两种方法传递一维数组:

1.1 在函数中将数组作为指针传递

函数定义如下:

void func(int *arr, int size)
 {
    // ...
}

在调用函数时,可以直接传递数组名作为实参:

int arr[10];
func(arr, 10);

在函数内部,可以通过指针访问数组中的元素,例如:

void func(int *arr, int size)
{
    for (int i = 0; i < size; i++)
    {
        printf("%d ",arr[i]);
    }
}

1.2 在函数中使用数组形式的参数

函数定义如下:

void func(int arr[], int size) 
{
    // ...
}

在调用函数时,也直接传递数组名作为实参:

int arr[10];
func(arr, 10);

和第一种方法类似,可以通过数组形式的参数访问数组中的元素:

void func(int arr[], int size)
{
    for (int i = 0; i < size; i++)
    {
        printf("%d ",arr[i]);
    }
}

1.3 知道了上面的方法,下面来看一个例子:

#include <stdio.h>
void test(int arr[])//ok?
{}
void test(int arr[10])//ok?
{}
void test(int *arr)//ok?
{}
void test2(int *arr[20])//ok?
{}
void test2(int **arr)//ok?
{}
int main()
{
 int arr[10] = {0};
 int *arr2[20] = {0};
 test(arr);
 test2(arr2);
}

arr是存放整形的数组
arr2是存放整形指针的数组

我们从上往下看:

一维数组传参,形参可以是
不带容量的一维数组,也可以带容量,也可以是指针,所以前三个很容易判断,都是正确的;

整形指针数组传参,可以类比整形数组传参:
整形数组传参:形参可以是整形数组,也可以是一级指针
整形指针数组传参:形参可以是整形指针数组,也可以是二级指针(arr2是存放整形指针的数组)

所以答案如下:

总的来说就是一维数组传参,形参可以是数组,也可以是指针,但当形参是指针的时候,要注意类型。

2. 二维数组传参

二维数组是一个由多个一维数组组成的数组,每个一维数组又由多个元素组成。在传参时,可以将二维数组传递给函数。

首先,定义一个二维数组并赋值:

int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};

然后,定义一个函数接受二维数组作为参数:

void printArr(int (*arr)[3]) {
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }
}

在调用函数时,将二维数组作为参数传递给函数即可:

printArr(arr);

其中,int (*arr)[3]表示一个指向由3个整数组成的一维数组的指针(也可以写成int arr[2][3]),arr代表整个二维数组的首地址。在函数内部,可以使用arr[i][j]来访问数组元素。

下面来看一个例题:

void test(int arr[3][5])//ok?
{}
void test(int arr[][])//ok?
{}
void test(int arr[][5])//ok?
{}
void test(int *arr)//ok?
{}
void test(int* arr[5])//ok?
{}
void test(int (*arr)[5])//ok?
{}
void test(int **arr)//ok?
{}
int main()
{
 int arr[3][5] = {0};
 test(arr);
}

二维数组传参,形参可以是指针,也可以是数组,
如果是数组,行可以省略,但列不能省略
如果是指针,传过去的是第一行的地址,形参就应该是数组指针

所以,答案如下:

但是,有的老铁可能用了上面错误的形参格式,但是最后还是能正常访问遍历数组,这是怎么一回事呢?

其实这是因为在参数传递的过程中编译器自动把代码给优化了,因为是指针,只要来的是个地址,它就接,但是我们应该尽量避免写出这样的代码,让我们的代码更加严密以及符合逻辑。

总结:
二维数组传参,函数形参的设计只能省略第一个[]的数字。
因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。这样才方便运算。

3. 一级指针传参

一级指针是指向变量的指针。当使用一级指针作为函数参数时,函数会接收该指针所指向的变量的地址,从而使函数能够直接修改该变量的值。

下面是一个使用一级指针传参的示例:

void print(int* p, int sz)
{
  int i = 0;
  for (i = 0; i < sz; i++)
  {
    printf("%d\n", *(p + i));
  }
}
int main()
{
  int arr[10] = { 1,2,3,4,5,6,7,8,9 };
  int* p = arr;
  int sz = sizeof(arr) / sizeof(arr[0]);
  //一级指针p,传给函数
  print(p, sz);
  return 0;
}

在上面的示例中,print函数的形式参数是一个指向整型的指针p,而实际参数是一个指向整型数组的指针p或者数组名arr。这样,print函数就可以通过p加上i来访问或打印数组arr的第i个元素,从而实现打印数组的功能。

在main函数中,定义一个长度为10的整型数组arr,并用1到9初始化。
定义一个指向整型的指针p,并让它指向arr的首元素,即p = arr。
定义一个整型变量sz,并用数组arr的总字节数除以单个元素的字节数得到,即sz = sizeof(arr) / sizeof(arr[0]),这样就得到了数组的长度。
调用print函数,传入指针p和数组长度sz,打印出数组arr的所有元素。

思考:当一个函数的参数部分为一级指针的时候,函数能接收什么参数?

一个指针变量,例如int* p = &a;,其中a是一个整型变量,p是一个指向整型的指针变量,可以将p作为参数传给函数。

一个数组名,例如int arr[10];,其中arr是一个长度为10的整型数组,arr也是一个指向数组首元素的指针,可以将arr作为参数传给函数。

一个地址常量,例如&b;,其中b是一个整型变量,&b表示b的地址,也是一个指向整型的指针常量,可以将&b作为参数传给函数。

如下:

4.二级指针传参

二级指针传参的意思是,函数的形式参数是一个指向指针的指针类型,而实际参数是一个指向指针的指针变量或者一个指针数组名。这样,函数就可以通过指针操作符来访问或修改实际参数所指向的指针或者指针数组的元素。

来看一个简单的例子:

void swap(int** p1, int** p2)
{
  int* tmp = *p1;
  *p1 = *p2;
  *p2 = tmp;
}
int main()
{
  int a = 10;
  int b = 20;
  int* pa = &a;
  int* pb = &b;
  //二级指针pa和pb,传给函数
  swap(&pa, &pb);
  printf("a=%d b=%d\n", a, b); //输出a=20 b=10
  printf("*pa=%d *pb=%d\n", *pa, *pb); //输出*pa=10 *pb=20
  return 0;
}

在上面这个例子中,swap函数的形式参数是一个指向整型指针的指针p1和p2,而实际参数是一个指向整型指针的指针变量pa和pb。这样,swap函数就可以通过p1和p2来交换pa和pb所指向的整型变量的值。二级指针传参的好处是,可以实现对指针的间接操作,提高程序的灵活性和扩展性

思考:当函数的参数为二级指针的时候,可以接收什么参数?

一个指向指针的指针变量,例如int** pp = &p;,其中p是一个指向整型的指针变量,pp是一个指向整型指针的指针变量,可以将pp作为参数传给函数。

一个指针数组名,例如int* arr[10];,其中arr是一个长度为10的整型指针数组,arr也是一个指向整型指针的指针,可以将arr作为参数传给函数。

一个地址常量,例如&c;,其中c是一个指向整型的指针变量,&c表示c的地址,也是一个指向整型指针的指针常量,可以将&c作为参数传给函数。

如下:

相关文章
|
6天前
使用指针访问数组元素
【10月更文挑战第30天】使用指针访问数组元素。
18 3
|
5天前
使用指针访问数组元素
【10月更文挑战第31天】使用指针访问数组元素。
12 2
|
17天前
|
存储 C语言 C++
如何通过指针作为函数参数来实现函数的返回多个值
在C语言中,可以通过将指针作为函数参数来实现函数返回多个值。调用函数时,传递变量的地址,函数内部通过修改指针所指向的内存来改变原变量的值,从而实现多值返回。
|
14天前
|
算法 索引
单链表题+数组题(快慢指针和左右指针)
单链表题+数组题(快慢指针和左右指针)
23 1
|
17天前
|
存储 搜索推荐 C语言
如何理解指针作为函数参数的输入和输出特性
指针作为函数参数时,可以实现输入和输出的双重功能。通过指针传递变量的地址,函数可以修改外部变量的值,实现输出;同时,指针本身也可以作为输入,传递初始值或状态。这种方式提高了函数的灵活性和效率。
|
23天前
|
存储
如何使用指针数组来实现动态二维数组
指针数组可以用来实现动态二维数组。首先,定义一个指向指针的指针变量,并使用 `malloc` 为它分配内存,然后为每个子数组分配内存。通过这种方式,可以灵活地创建和管理不同大小的二维数组。
|
23天前
|
存储
如何通过指针数组来实现二维数组?
介绍了二维数组和指针数组的概念及其区别,详细讲解了如何使用指针数组模拟二维数组,包括定义与分配内存、访问和赋值元素、以及正确释放内存的步骤,适用于需要动态处理二维数据的场景。
|
23天前
|
存储 算法 C语言
C语言:什么是指针数组,它有什么用
指针数组是C语言中一种特殊的数据结构,每个元素都是一个指针。它用于存储多个内存地址,方便对多个变量或数组进行操作,常用于字符串处理、动态内存分配等场景。
|
29天前
魔法指针 之 二级指针 指针数组
魔法指针 之 二级指针 指针数组
16 1
|
1月前
|
存储
一篇文章了解区分指针数组,数组指针,函数指针,链表。
一篇文章了解区分指针数组,数组指针,函数指针,链表。
17 0

热门文章

最新文章

下一篇
无影云桌面