C 当我以数组名作为参数调用函数时会发生什么?

C 当我以数组名作为参数调用函数时会发生什么?,c,arrays,function,pointers,C,Arrays,Function,Pointers,我正在阅读K&R的TCPL,当我阅读有关数组和指针的内容时,我在下面编写了以下小代码: #include <stdio.h> int sum(int a[]) { int t = 0; int length = sizeof(a) / sizeof(a[0]) ; // printf("%d\n",length); for(int i = 0; i != length; ++i) { t += a[i]; } retu

我正在阅读K&R的TCPL,当我阅读有关数组和指针的内容时,我在下面编写了以下小代码:

#include <stdio.h>
int sum(int a[])
{
    int t = 0;
    int length = sizeof(a) / sizeof(a[0]) ;
//  printf("%d\n",length);
    for(int i = 0; i != length; ++i)
    {
        t += a[i];
    }
    return t;
}
int main()
{
    int b[5] = {1, 2, 3, 4, 5};
    printf("%d\n",sum(b));
    return 0;
}
#包括
整数和(整数a[]
{
int t=0;
int length=sizeof(a)/sizeof(a[0]);
//printf(“%d\n”,长度);
for(int i=0;i!=length;++i)
{
t+=a[i];
}
返回t;
}
int main()
{
int b[5]={1,2,3,4,5};
printf(“%d\n”,和(b));
返回0;
}
输出答案是1而不是15,然后我通过添加
printf(“%d\n”,length)调试此代码输出长度为1而不是5。
TCPL告诉我们,当数组名用作参数时,数组名会转换为指针,但输出答案是错误的,所以我想知道:

  • 使用数组名作为参数调用函数时会发生什么
  • sum(int a[])
    中使用的数组
    a[]
    参数是否有存储
  • 我在调用数组时看到两种样式:
    fun(inta[]);fun(b)
    fun(int*a);乐趣(b)
    ,有什么区别

  • 非常感谢:-)

    您不能调用函数并传递整个数组;如果使用数组名作为函数参数,它将被隐式重写为指向其第一个元素的指针(“decays to”)。这相当于写作

     int sum(int *a) { ... }
    
    因此,在函数中,
    sizeof array
    ,不提供数组的大小,只提供指向其第一个元素的指针的大小


    那么如何知道数组中有多少个元素呢?您需要将这个数字显式地传递给函数(或者定义一个包含元素数量的宏,并在需要时使用它)。

    您不能调用函数并传递整个数组;如果使用数组名作为函数参数,它将被隐式重写为指向其第一个元素的指针(“decays to”)。这相当于写作

     int sum(int *a) { ... }
    
    因此,在函数中,
    sizeof array
    ,不提供数组的大小,只提供指向其第一个元素的指针的大小


    那么如何知道数组中有多少个元素呢?您需要将这个数字显式地传递给函数(或者用元素的数量定义一个宏,并在需要时使用它)。

    在声明如下的数组上调用
    sizeof

     int a[5];
    

    将以您当前认为的方式返回数组的大小(即以字节为单位的数组的完整大小-在我的机器上为20字节)。当您将这样的数组传递给函数时,该数组将衰减为指向其第一个元素的指针。因此,当您在函数参数上调用
    sizeof
    时,实际上是在指针上调用它。如果您将函数声明为接受
    int*
    参数,那么错误会更明显,因为您调用的
    sizeof
    变量的类型是显式的

    在声明如下的数组上调用
    sizeof

     int a[5];
    

    将以您当前认为的方式返回数组的大小(即以字节为单位的数组的完整大小-在我的机器上为20字节)。当您将这样的数组传递给函数时,该数组将衰减为指向其第一个元素的指针。因此,当您在函数参数上调用
    sizeof
    时,实际上是在指针上调用它。如果您将函数声明为接受
    int*
    参数,那么错误会更明显,因为您调用的
    sizeof
    变量的类型是显式的

    您的第三个问题触及了问题的核心:就编译器而言,这两个问题没有区别。关于论点是如何传递的,一切都是一样的

    因此,在回答第二个问题时,
    a
    参数没有底层数组的存储,也没有复制该数组的成员。唯一分配给
    int*
    指针的存储,该指针存储在
    a
    中。(这也多少回答了你的第一个问题。)

    因此,在您的功能中:

    int length = sizeof(a) / sizeof(a[0]) ;
    
    相当于

    int length = sizeof(int *) / sizeof(int);
    

    在指针和整数大小相同的系统上返回1。如果你在64位Linux上运行这个程序,你会得到2,因为指针是64位的,整数是32位的。

    你的第三个问题触及了问题的核心:就编译器而言,这两者之间没有区别。关于论点是如何传递的,一切都是一样的

    因此,在回答第二个问题时,
    a
    参数没有底层数组的存储,也没有复制该数组的成员。唯一分配给
    int*
    指针的存储,该指针存储在
    a
    中。(这也多少回答了你的第一个问题。)

    因此,在您的功能中:

    int length = sizeof(a) / sizeof(a[0]) ;
    
    相当于

    int length = sizeof(int *) / sizeof(int);
    

    在指针和整数大小相同的系统上返回1。如果您在64位Linux上运行此函数,您将得到2,因为指针是64位的,int是32位的。

    您的调用没有问题,而且
    fun(int a[])
    fun(int*a)
    之间没有区别(读者更清楚地看到,您需要的是数组,而不是任何指针)。Bot参数是指向int的指针


    这里的问题是如何确定数组的长度。由于方括号是空的,编译器无法知道
    a
    后面的数组有多长。例如,可以将数组的长度作为第二个参数提供。注意:调用函数时,
    sizeof(b)
    将提供正确的长度,因为编译器知道它的长度。

    您的调用没有问题,
    fun(int a[])
    fun(int*a)
    (读者应该更清楚地看到,您需要的是数组而不是任何指针)。Bot参数是指向int的指针

    你这里的问题是你如何决定