关于C++中sizeof()、数组长度和函数传参的一点心得

来源:互联网 发布:windows黑苹果双系统 编辑:程序博客网 时间:2024/06/09 22:53

        以前上C++课程的时候老师曾经解释过C++中数组名的意义:一般来说数组名可以看作是这个数组第一个元素的地址。然后后来便一直以为数组名和指针并没有任何不同。直到昨天做了一些题目,才发现其中仍有一些端倪,所以后来上网查了资料,自己也做了一下实验,才把其中的一些差别之处真正弄明白。

        先来看看下面这一小段代码:

int main(){    int a[5];    int *b = new int[5];    cout<<sizeof(a)<<' '<<sizeof(&a)<<' '<<sizeof(b)<<endl;    delete b;    return 0;}
        输出结果很容易猜到:

20 8 8
        (我的机子是64位系统的,所以指针的大小都是8Byte)

        从sizeof(&a) 我们可以知道,a确实是指向数组首地址的int类型指针,但是对于这种静态数组,sizeof返回的是整个数组的长度,而不是a的大小。对比之下,b就是单纯的指向动态数组的首地址的int指针了,而且sizeof(b)只能获得指针大小,没有办法获得整个数组的大小。如果想要返回数组的大小,需要把数组封装一下,加入长度变量记录才行。

        这样看来,对于sizeof()函数来说,静态数组名和一般的变量指针还是有一点区别的。然而,如果要把一个数组当作参数传入函数中时,又有一些特别的注意事项。再看看一下代码:

void getLength(int arr[5]){    cout<<sizeof(arr)<<endl;}int main(){    int a[5];    getLength(a);    return 0;}
        程序输出:
8

        原因很简单,在函数传参中数组都是以传指针的形式传入函数的,并不会出现传值调用。在函数形参中,int arr[5] 会退化成 int *,那个5就丢失了,所以getLength函数中arr实际上只是单纯的数组a的首地址。也就是说,形参列表中写int arr[5], int arr[] , int *arr 效果都是一样的。但是如果要想同时传入数组的指针和数组的大小,一般可以有两种做法:

        1. 把数组长度作为函数的另一个形参:

void getLength(int arr[], int num);
        2. 使用引用
void getLength(int (&arr)[5]);
        这种方法中数组的长度就能传进函数了。但是使用这种方法的时候,如果外部函数传进来的数组长度不是5,编译器会报错。

        既然讲到了数组引用,我又看到一个关键的点,想拿出来和大家一同分享:对于数组 a[5]来说,a和&a是有不同的含义的。再看看下面的代码:

int main(){    int a[4] = {1,2,3,4};    int * a_ptr =  (int *)(&a +1);    cout<< *(a+1) << ' '<<  *(a_ptr-1) <<endl;    return 0;}
        输出结果:
2 4
        原因是这样:a在这里仍然是静态数组 {1,2,3,4}的首个元素的地址,所以*(a+1)就是把a移动到下一个元素,解引用后输出,很好理解;然而&a代表的是整个长度为4个元素的数组。所以 &a +1 并不是单纯地移动到下一个元素,而是根据数组的长度移动数组长度个单位,即此时 &a +1指向的是4后面的元素(溢出),所以最后 *(a_ptr-1)输出的就是最后一个元素4了。

        匆忙之中,写下一些心得记录,使自己能铭记于心。        



0 0