c++里面的函数学习 day2

2.3 数组形参
在函数中对数组中的值的修改,会影响函数外面的数组。

一维数组形参的写法:

// 尽管形式不同,但这三个print函数是等价的
void print(int *a) {/* … */}  //这个是在数据结构的代码中或者是c语言或者c++的学习过程中,书上的

那种课后习题里面经常出现,等后面学了指针就会渐渐熟悉这种表示方式了。
void print(int a[]) {/* … */}   //这个和第三种其实差不多,只是不写数组的长度罢了。
void print(int a[10]) {/* … */} //这个属于是怎么定义的就怎么写。

 示例代码如下(用的是第三种方法来写的):

#include 

using namespace std;

int output(int n, int a[5])
{
/*没有n也就无法遍历数组里面的元素将其输出了,这个函数可以理解为是传了两个参数的函数,与之前传一个
有区别*/
    for (int i = 0; i < n; i++)
        cout << a[i] << ' ';
    cout << endl;
}
int main()
{
    int a[5] = {1, 2, 3, 4, 5};
    output(5, a);

    return 0;
}

在这段代码中,output(5, a)是函数调用语句,用于调用名为output的函数,并传递两个参数:5和数组a。

  具体来说,output(5, a)表示调用名为output的函数,并传递两个参数:5和数组a。这里的5是一个整数,表示数组a中元素的数量。a是一个整型数组,它包含了5个元素。

在函数调用时,参数5会被传递给函数的第一个形参n,而数组a会被传递给函数的第二个形参a。这样,在函数内部,形参n的值将为5,形参a将指向数组a的首地址。

在函数output内部,通过使用形参n和a,我们可以遍历数组a并输出其中的元素。在这个例子中,函数output会输出数组a中的所有元素,即1 2 3 4 5。

总结起来,output(5, a)表示调用名为output的函数,并传递参数5和数组a。在函数内部,我们可以使用这些参数来执行特定的操作,例如遍历数组并输出元素。

多维数组形参的写法:

// 多维数组中,除了第一维之外,其余维度的大小必须指定
void print(int (*a)[10]) {/* … */} /*这是用指针写的样子,和一维数组时很像,但是这里要注意,只要是多维数组传参,要用指针的格式来写,那必须用一个括号将指针符号和数组名字给括起来,形成所谓的数组指针,关于什么是数组指针,我后面会详细解释,还请各位不要着急。*/
void print(int a[][10]) {/* … */}

/*只要是多维数组,如果用数组原来的表达方式写的话,那么永远都是第一个中括号里面可以没有数字,但是后面的中括号里面必须都有数字,这是规定。

多维数组传参和一些知识点如下:

示例代码:

#include 
// 传多维数组形参
using namespace std;

void output(int n, int m, int a[][2])
/*n,m表示每一维数组的长度,例如这里初始化的是a[2][2],那么这里n=2,m=2,反正这两个数的值看情况而定。
最后那个是传的二维数组的参数。a数组的第一个中括号可省略,后面的不行。
*/
{
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            cout << a[i][j] << ' ';
            /*多维数组里面元素的输出。这里注意,要想输出类似于正方形的样子,那么就必须在i取一个值,j循环完一遍时,
            马上换行,继续输出第二行的元素,以此类推。
            */
           a[i][j] = 1;
           /*在这里我把a[i][j]全部赋值为1,就相当于在一个函数里面修改了内部形参的值,我将用此来验证
           函数内部形参数组内容的变化是否会影响原输入数组的改变。*/
           
           
        }
        cout << endl; /*这个回车是每一次循环结束后才回车,而不是输出一个元素就回一次车,不然输出的每行
         都只有一个元素,就不能像正方形那样排列了。*/
    }
}

int main()
{
    // 这里初始化一个二维数组。
    int a[2][2] = {
        {4, 7},
        {9, 6},
    };

    output(2, 2, a);
    // 格式仍然固定,几维数组那么就有几个数字,那最后面一定是数组名。
    puts(" ");//这句没啥别的意思,单纯是为了输出的时候有能隔一行。

    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 2; j++)
            cout << a[i][j] << ' ';

        cout << endl;
    }

    return 0;
}

这个代码的输出为 :

4 7
9 6

1 1
1 1

由输出数据可以看出,第一次输出的时候是调用的output函数,这个时候是正常输出,所以输出的是原数组。这里注意,那个函数里面我赋值的二维数组全是1这个元素的那一句语句,是在输出的后面的,是不会影响我前面正常的输出的。

因为在输出的后面加上了这么一句语句,改变了函数内部原形参的值,所以也把原输入的内容给改变了,成为了新改变的二维数组。

总结:改变数组里面的内容也是会影响原来输入的内容,这个和传引用参数性质是一样的。

2.4 数组指针与指针数组的概念和区分

int (*a)[10]是一个数组指针(pointer to an array),而不是指针数组(array of pointers)。

数组指针是指向数组的指针,它指向的是整个数组,而不是数组中的单个元素。在这个例子中,a是一个指针,它指向一个包含10个整数的数组。他这里之所以要用括号括起来,就是想表示这个a是一个指针,表示先操作括号里面的东西。

指针数组是一个数组,其中的元素都是指针。每个元素都指向不同的对象或变量。例如,int* a[10]表示一个包含10个指针的数组,每个指针都可以指向一个整数。这里前面没有用括号括起来,那么就已经说明了a不是一个指针,只是想表示这个数组里面的元素都是指针而已。

为了更好地理解数组指针和指针数组的区别,我们可以通过以下示例来说明:

int main()
{
    int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    int (*ptr)[10];  // 声明一个数组指针,这样为后面获取地址里面的值做了铺垫。
   
    ptr = &arr;  // 将数组的地址赋值给指针
   /*这里&arr这个操作,把arr数组里面的每一个元素的地址都获取了。形象的理解为:
数组是连续的很多一个一个的小方框,而&arr取得就是这每个方框的位置,就像确定了萝卜坑里的坑,取的只是一个位置。
而ptr这个变量,就是接收这每个萝卜坑的位置。因为前面已有声明,ptr是数组指针,之前声明数组指针的时候只是表示指向一个整型数组,而&arr这一步直接让ptr这一个数组指针指向arr这一个整型数组,换句话说就是这个ptr指向了arr数组里面的所有小方框,是指向的一个大的整体,而不是单单只是小方框里面的一个元素或者只指向一个小方框。*/
    for (int i = 0; i < 10; i++)
    {
        cout << (*ptr)[i] << " ";  // 通过指针访问数组元素
   /*这里通过解引用指针来获取arr数组里面的每个元素,用for循环来实现连续的输出。
    解释:ptr是已经获取了arr这整个数组方框的地址,而*ptr则是获取这一整个大方框里面的所有数据。
而后面的(*ptr)[i]其实就和普通的数组下标取数是一样的了。(*ptr)已经将一段连续的方框全部变为了数据,用上面的代码来说就是全转换为了{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}这十个数字。相当于只看数据,不看框框了,就像一连串的数据一样,例如当i取0是,取得数据1;当i是2时,取得数据2......以此类推。

后面的操作其实就是数字的遍历了,利用循环把这些数据都输出出来,和我们以前学习的操作一样。*/
    }

    return 0;
}







/*在上面的示例中,我们声明了一个数组arr,其中包含10个整数。然后,我们声明了一个数组指针ptr,它指向一个包含10个整数的数组。通过将数组arr的地址赋值给指针ptr,我们使得指针ptr指向了数组arr。

在循环中,我们通过解引用指针ptr来访问数组元素。这里的(*ptr)[i]表示先解引用指针ptr,然后再通过索引i访问数组元素。这样,我们可以逐个输出数组arr中的元素。

总结起来,int (*a)[10]是一个数组指针,它指向一个包含10个整数的数组。数组指针指向整个数组,而指针数组是一个包含指针的数组,每个指针可以指向不同的对象或变量。*/

其中一些语句的含义与作用:

int (*ptr)[10];这一句是用来声明一个指向包含10个整数的数组的指针。(括号不可省略)

具体来说,int (*ptr)[10];声明了一个名为ptr的指针变量,它指向一个包含10个整数的数组。

为什么要使用这样的声明呢?这是因为在C++中,数组名本身就是一个指针,它指向数组的第一个元素。而在这个例子中,我们想要指向整个数组,而不仅仅是数组的第一个元素。因此,我们需要使用数组指针来实现这个目的。

通过声明int (*ptr)[10];,我们创建了一个指针变量ptr,它可以指向一个包含10个整数的数组。这样,我们就可以通过ptr来访问整个数组,而不仅仅是数组的第一个元素。

在上面的代码示例中,我们将数组arr的地址赋值给了指针ptr,使得指针ptr指向了数组arr。然后,在循环中,通过解引用指针ptr,我们可以访问数组arr中的每个元素。

所以,int (*ptr)[10];这一句是用来声明一个指向包含10个整数的数组的指针,它的作用是让指针能够指向整个数组,而不仅仅是数组的第一个元素。如果不使用这样的声明,我们将无法通过指针访问整个数组。

2.5 解引用指针的含义与运用

解引用指针是指通过指针访问指针所指向的内存地址中存储的值。

在C++中,指针是一个变量,它存储了一个内存地址。通过指针,我们可以间接地访问和操作内存中的数据。而解引用指针就是使用指针来获取指针所指向的值。

解引用指针使用的操作符是*,放在指针变量的前面。当我们对一个指针进行解引用操作时,编译器会根据指针的类型,找到指针所指向的内存地址,并返回该地址中存储的值。

例如,假设我们有一个指针变量ptr,它指向一个整数变量num的内存地址。通过解引用指针*ptr,我们可以获取到num变量的值。

int num = 10; // 定义一个整数变量
int* ptr = # // 定义一个指向整数变量的指针,将num的地址赋值给ptr

cout << *ptr; // 解引用指针ptr,输出num的值

在上面的代码中,*ptr就是对指针ptr进行解引用操作,它返回了指针所指向的内存地址中存储的值,即num的值。通过输出*ptr,我们可以得到num的值,即10。

解引用指针是一种非常重要的操作,它允许我们通过指针来访问和修改内存中的数据。通过解引用指针,我们可以间接地操作指针所指向的变量,实现更灵活和动态的内存管理。

有些时候"*"这个符号只是想表示那个变量是一个指针,而有些时候就是解引用指针,用来获取值的,根据实际情况来分析,不可一概而论。

总之,一定要注意定义指针变量的时候要加括号,表明是一个指针。若没有括号,就得想想是不是指针数组了。这两个概念是很难理解的,也比较绕,我也通过自己写一些代码例子来帮助大家更好的理解这两个概念,希望大家能沉下心来,好好的去理解这些知识,慢慢看。

你可能感兴趣的:(c++,学习,开发语言)