一维数组作为函数形参

转载:https://blog.csdn.net/oNever_say_love/article/details/49422517

一、一个例子引发的思考

  运行以下代码,请问输出是什么?例子来源于《剑指Offer》,我对书上例子做了修改,让其可以运行。

#include<iostream>
using namespace std;

int GetSize(int data[]) {
    return sizeof(data);
}
int main() {
    int data1[] = {1,2,3,4,5};
    int size1 = sizeof(data1);

    int *data2 = data1;
    int size2 = sizeof(data2);

    int size3 = GetSize(data1);

    cout<<size1<<" "<<size2<<" "<<size3<<endl;
    return 0;
}

    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

运行结果如下:
这里写图片描述
  data1是一个数组,sizeof(data1)是求数组的大小。这个数组包含5个整数,每个整数占4个字节,因为总共是20个字节。data2声明为指针,尽管它指向了数组data1,对认真指针求sizeof,得到的结果都是4。在C/C++中,当数组作为函数的参数进行传递时,数组就自动退化为同类型的指针。因此尽管函数GetSize的参数data被声明为数组,但它会退化为指针,size3的结果仍然是4.

二、数组的两个特殊性质

(1)不允许拷贝和赋值

  不能将数组的内容拷贝给其他数组作为其初始值,也不能用数组为其他数组赋值。

int a[] = {0,1,2};    // 含有三个整数的数组
int s2 = a;           // 错误:不允许使用一个数组初始化另一个数组
a2 = a;               // 错误:不能把一个数组直接赋值给另一个数组
    
    
  • 1
  • 2
  • 3

(2)使用数组是通常将其转化成指针

  在C++语言中,指针和数组有非常紧密的联系。使用数组的时候编译器一般会把它转换成指针。

  通常情况下,使用取地址符来获取指向某个对象的指针,取地址符也可以用于任何对象。数组的元素也是对象,对数组使用下标运算符得到该数组指定位置的元素。因此像其他对象一样,对数组的元素使用取地址符就能的搭配指向该元素的指针:

string nums[] = {"one", "two", "three"};  // 数组元素是string对象
string *p = &nums[0];                     // p指向nums的第一个元素
    
    
  • 1
  • 2

  然而,数组还有一个特性:在很多用到数组名字的地方,编译器都会自动地将其替换为一个指向数组首元素的指针:

string *p2 = nums;                        // 等价于p2 = &nums[0]
    
    
  • 1

  在大多数表达式中,使用数组类型的对象其实是使用一个指向该数组首元素的指针。

三、数组形参

  数组的两个特殊性质对我们定义和使用作用在数组上的函数有影响。因为不能拷贝数组,所以我们无法以值传递的方式使用数组参数。因为数组会被转换成指针,所以当我们为函数传递一个数组时,实际上传递的是指向数组首元素的指针。
  尽管不能以值传递的方式传毒数组,但是我们可以把形参写成类似数组的形式:

//尽管形式不同,但这三个print函数是等价的
//每个函数都有一个const int*类型的形参
void print(const int*);
void print(const int[]);
//这里的维度表示我们期望数组含有多少元素,实际不一定
void print(const int[10]); 
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

  尽管表现形式不同,但上面的三个函数是等价的:每个函数的唯一形式都是const int*类型的。当编译器处理对print函数的调用时,只检查传入的参数是否是const int*类型:

int i=0,j[2] = {0,1};
print(&i);               //正确:&i的类型是int*
print(j);                 //正确:j转船成int* 并指向j[0]
    
    
  • 1
  • 2
  • 3

  如果我们传给print函数的是一个数组,则实参自动地转换成指向数组首元素的指针,数组的大小对函数的调用没有影响。

  和其他使用数组的代码一样,以数组作为形参的函数也必须确保使用数组时不会越界。

                                            <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/production/markdown_views-ea0013b516.css">
                                </div>

一、一个例子引发的思考

  运行以下代码,请问输出是什么?例子来源于《剑指Offer》,我对书上例子做了修改,让其可以运行。

#include<iostream>
using namespace std;

int GetSize(int data[]) {
    return sizeof(data);
}
int main() {
    int data1[] = {1,2,3,4,5};
    int size1 = sizeof(data1);

    int *data2 = data1;
    int size2 = sizeof(data2);

    int size3 = GetSize(data1);

    cout<<size1<<" "<<size2<<" "<<size3<<endl;
    return 0;
}

  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

运行结果如下:
这里写图片描述
  data1是一个数组,sizeof(data1)是求数组的大小。这个数组包含5个整数,每个整数占4个字节,因为总共是20个字节。data2声明为指针,尽管它指向了数组data1,对认真指针求sizeof,得到的结果都是4。在C/C++中,当数组作为函数的参数进行传递时,数组就自动退化为同类型的指针。因此尽管函数GetSize的参数data被声明为数组,但它会退化为指针,size3的结果仍然是4.

二、数组的两个特殊性质

(1)不允许拷贝和赋值

  不能将数组的内容拷贝给其他数组作为其初始值,也不能用数组为其他数组赋值。

int a[] = {0,1,2};    // 含有三个整数的数组
int s2 = a;           // 错误:不允许使用一个数组初始化另一个数组
a2 = a;               // 错误:不能把一个数组直接赋值给另一个数组
  
  
  • 1
  • 2
  • 3

(2)使用数组是通常将其转化成指针

  在C++语言中,指针和数组有非常紧密的联系。使用数组的时候编译器一般会把它转换成指针。

  通常情况下,使用取地址符来获取指向某个对象的指针,取地址符也可以用于任何对象。数组的元素也是对象,对数组使用下标运算符得到该数组指定位置的元素。因此像其他对象一样,对数组的元素使用取地址符就能的搭配指向该元素的指针:

string nums[] = {"one", "two", "three"};  // 数组元素是string对象
string *p = &nums[0];                     // p指向nums的第一个元素
  
  
  • 1
  • 2

  然而,数组还有一个特性:在很多用到数组名字的地方,编译器都会自动地将其替换为一个指向数组首元素的指针:

string *p2 = nums;                        // 等价于p2 = &nums[0]
  
  
  • 1

  在大多数表达式中,使用数组类型的对象其实是使用一个指向该数组首元素的指针。

三、数组形参

  数组的两个特殊性质对我们定义和使用作用在数组上的函数有影响。因为不能拷贝数组,所以我们无法以值传递的方式使用数组参数。因为数组会被转换成指针,所以当我们为函数传递一个数组时,实际上传递的是指向数组首元素的指针。
  尽管不能以值传递的方式传毒数组,但是我们可以把形参写成类似数组的形式:

//尽管形式不同,但这三个print函数是等价的
//每个函数都有一个const int*类型的形参
void print(const int*);
void print(const int[]);
//这里的维度表示我们期望数组含有多少元素,实际不一定
void print(const int[10]); 
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

  尽管表现形式不同,但上面的三个函数是等价的:每个函数的唯一形式都是const int*类型的。当编译器处理对print函数的调用时,只检查传入的参数是否是const int*类型:

int i=0,j[2] = {0,1};
print(&i);               //正确:&i的类型是int*
print(j);                 //正确:j转船成int* 并指向j[0]
  
  
  • 1
  • 2
  • 3

  如果我们传给print函数的是一个数组,则实参自动地转换成指向数组首元素的指针,数组的大小对函数的调用没有影响。

  和其他使用数组的代码一样,以数组作为形参的函数也必须确保使用数组时不会越界。

                                            <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/production/markdown_views-ea0013b516.css">
                                </div>

猜你喜欢

转载自blog.csdn.net/wangkui1331/article/details/80078988