c中自定义函数通过sizeof来输出数组的长度为何不正确?【原创】

这两天,在学习C语言的时候遇到一个bug。后来就在segmentfault提问,通过网友的回答也就解决了这个问题。提问的问题链接是:c中自定义函数通过sizeof来输出数组的长度为何不正确?


在C语言中,获取数组的长度大小,即元素个数一般用 sizeof(arr)/sizeof(arr[0])来表示。即:
#include <stdio.h>  
int main(){
    double arr[]={1.78, 1.77, 1.82, 1.79, 1.85, 1.75, 1.86, 1.77, 1.81, 1.80};
    int length = sizeof(arr)/sizeof(arr[0]);
    printf("main里面的数组长度为%d
",length);   //正常输出, 10
    return 0;
}

结果输出:会正常输出元素的个数的。

但如果写成一个函数的方式,把数组作为函数的参数传入的话。即:
<pre name="code" class="cpp">#include <stdio.h>  

int arr_str(double a[]) {
    int len=sizeof(a)/sizeof(a[0]);  //1  
    return len;
}

int main(){
    double arr[]={1.78, 1.77, 1.82, 1.79, 1.85, 1.75, 1.86, 1.77, 1.81, 1.80};
    printf("arr_str里面的数组长度为%d
",arr_str(arr));
    return 0;
}

结果输出:显示不了数组的长度,而是1。

原因在于:第一,在c中,数组在作为参数的时候就退化为指针,对一个地址来取大小呢,如果是32位系统的话即为4,如果是64位系统的话为8,所以呢,在函数中sizeof获取的是指针的长度而不是数组的长度。第二呢,在函数中,sizeof的处理时间的在编译期,也就是说对于动态生成的数组大小是不能用sizeof来算出来的。

解决办法:
第一种办法:
把数组作为参数传入到数组的同时呢,也传入该数组的长度进去。不过该办法需要在函数外获取该数组的长度才传进去,略显麻烦。
第二种办法:(推荐)
使用宏定义
如:
#include <stdio.h>  
#define ARR_LENGTH(arr)    sizeof(arr)/sizeof(arr[0])

int main(){
    double arr[]={1.78, 1.77, 1.82, 1.79, 1.85, 1.75, 1.86, 1.77, 1.81, 1.80};
    printf("宏定义里面的数组长度为%d
",ARR_LENGTH(arr));
    return 0;
}

第三种办法:(目前不知如何实现)
template <size_t N>
long calc(long (&array)[N]) // 利用模板传递参数 array是数组的引用
{
    long res = 0L;

    for (size_t i = 0;i < N;i ++) {
        res += array[i];
    }

    return res;
}

int main()
{
    long longarr[] = {1, 23, 4, 45, 46, 57,};

    long sum = calc(longarr);
}

补充:第三种办法是网友的建议,C++可以用vector等容器避免大部分数组的操作,对于字符数组也有string可以替代,也有可以传递数组大小的奇迹淫巧。如果你需要计算数组长度的函数,可以使用宏定义 或者 如果是C++,也用相应的模板技巧,这比宏定义安全。
原文地址:https://www.cnblogs.com/linewman/p/9918135.html