【问题标题】:Passing array to function vs Passing variables to function将数组传递给函数与将变量传递给函数
【发布时间】:2020-07-28 05:51:38
【问题描述】:

在开始之前,我想告诉你我正在学习编程。

在 C 中将变量传递给函数和将数组传递给函数有什么区别?

当我们将变量传递给函数时,我们只是传递函数的值。但是当我们传递一个数组时,我们以某种方式传递了一个指针,因为当我们在函数内部对数组进行一些更改时,实际的数组会发生变化。

为了让我的问题更清楚,我附上代码来解释我在问什么-

代码 1:

//Passing variable to function
#include<stdio.h>
void swap(int x, int y);
int main(void)
{
//Nothing is happening to real values of variables
    int x, y;
    x = 1; 
    y = 2;
    swap(x, y);
    printf("%d = x \n %d = y", x, y);
}

void swap(int x, int y)
{
    int temp;
    temp = x;
    x = y;
    y = temp;
}

代码 2:

//Here you can see the values of arrays are swapped.
#include<stdio.h>
void swap(int arr[]);


int main(void)
{
    int idx, array[2];
    for(idx = 0; idx < 2; idx++ )
    {
        scanf("%d", &array[idx]);
    }
    swap(array);
    for(idx = 0; idx < 2; idx++, printf("\n"))
    {
        printf("%d", array[idx]);
    }
}

void swap(int arr[])
{
    int temp;
    temp = arr[0];
    arr[0] = arr[1];
    arr[1] = temp;
}

也许我的问题还不清楚,但我只是想知道为什么数组的值会在 main 函数中发生变化,因为当我们调用函数时,我们只是传递了该变量的函数值。

【问题讨论】:

  • 基本上就是你说的那样。你传递一个变量,然后传递变量的值。您传递一个数组,然后传递指向该数组第一个元素的指针。那么你的问题是什么?
  • 因为数组是作为指针传递的,所以函数直接对数组的值进行操作。数组值不会复制到函数中。
  • 数组通过指针传递有两个原因。 1)节省时间。 2)节省空间。如果数组有 2 个元素,这些都不重要。如果数组有 200 万个元素,这两者都很重要。
  • 你基本上是对的。也许question about array to pointer decay 对你来说很有趣。
  • 请注意,在第一个示例中,您不会在 main() 中交换 x 和 y 的值。你只在swap() 中更改x 和y,这没什么用。

标签: c arrays function pointers parameters


【解决方案1】:

在这两种情况下,当您所说的变量被传递给函数或数组被传递给函数时,都会传递一个值。

但是在第一种情况下,传递了变量的值,而在第二种情况下,传递了指向数组第一个元素的指针的值。

表达式中使用的数组(极少数例外)被转换为指向其第一个元素的指针。

来自 C 标准(6.3.2.1 左值、数组和函数指示符)

3 除非它是 sizeof 运算符的操作数或一元 & 运算符,或者是用于初始化数组的字符串文字, 具有“类型数组”类型的表达式被转换为 类型为“pointer to type”的表达式,指向初始 数组对象的元素并且不是左值。如果数组对象 有注册存储类,行为未定义。

因此,有了指向对象的指针,您就可以更改指向的对象。

假设你有两个函数。

void f( int x )
{
   x = 10;
}

and

void g( int *px )
{
    *px = 10;
}

和他们的电话

int n = 0;

f( n );
g( &n );

您可以通过以下方式想象函数定义及其调用

int n = 0;

f( n );
g( &n );

//...

void f( /* int x */ )
{
   int x = n;
   x = 10;
}

void g( /* int *px */ )
{
    int *px = &n;
    *px = 10;
}

这两个函数都处理用作函数参数的表达式值的副本。但是如果函数g作为函数获取指向对象n的地址值,您可以使用指针(地址)更改指向对象n。

在 C 语言中,通过指向对象的指针间接将对象传递给函数称为通过引用传递。

来自 C 标准

——指针类型可以派生自函数类型或对象 类型,称为引用类型。 指针类型描述了一个对象 其值提供对被引用实体的引用 type. 从引用的类型 T 派生的指针类型有时是 称为“指向 T 的指针”。从一个指针类型的构造 引用类型称为“指针类型派生”。指针类型 是一个完整的对象类型。

注意这样的函数声明

void f( int a[], size_t n );

等价于下面的声明

void f( int *a, size_t n );

两者都声明了同一个函数。

如果你有一个数组,例如

#define N 10
//...
int a[N];

然后将其传递给函数

f( a, N );

然后,从 C 标准的第一个引用开始,数组指示符被转换为指向其第一个元素的指针。并且在函数中有这个指针,您可以更改数组的任何元素,因为实际上数组的每个元素都是通过引用传递的。使用指针算法,您可以更改指向数组的任何元素。例如

void f( int *a, size_t n )
{
    for ( int i = 0; i < n; i++ )
    {
        a[i] = i;
        // that is the same as
        // *( a + i ) = i;
    }
}

【讨论】:

  • 其他答案中的最佳解释(也很好)。
  • 两个吹毛求疵的注意事项: 1. 第二个引用的确切参考部分可能有用。 2. 你也许应该解释一下为什么你将元素的数量作为单独的参数传递(因为数组大小不能在被调用的函数中确定)。
【解决方案2】:

当你传递一个数组时,你实际上传递的是它的基地址,它是一个指向内存中第一个数组元素的指针。它本质上是一个引用调用,因此您不需要在传递给您的交换函数时显式使用引用或&amp;。 arr 衰减为 &amp;(arr[0])。

另一方面,变量默认情况下不是按值传递的,您需要显式使用&amp; 通过引用传递它们,以便在它们的内存位置交换它们的值,而不仅仅是特定于交换功能。

【讨论】:

  • 谢谢我真的很困惑为什么实际的数组会被改变所以谢谢
  • @DeathNet123 随时:)
【解决方案3】:

在C语言中将变量传递给函数和将数组传递给函数有什么区别?

您不能将数组原样传递给函数。 C 语法不允许这样做。当您提供数组的标识符作为参数时,它会衰减为指向数组第一个元素的指针 - 因此您通过引用数组的第一个元素来传递数组。

如果函数的相对参数是匹配指针类型,这里int *或int a[],这是允许的。

当提供一个变量作为参数时,你通过值传递它。意味着您不访问作为函数本身的参数提供的变量。而是将值复制到函数的局部变量中。

如果你想改变传递给自己的变量的值,你需要使用&amp; & 运算符来收集变量本身的地址。仅当相对参数与上述指针类型匹配时才允许这样做。


因此,在第一个示例中,您不会在 main() 中交换 x 和 y 的值。您只在 swap() 中更改 x 和 y ,这是非常没用的。

如果您想在 main 中交换 x 和 y,您需要将 swap() 定义为:

void swap(int* x, int* y)
{
    int temp;
    temp = *x;
    *x = *y;
    *y = temp;
}

并致电swap() 喜欢:

swap(&x, &y);

我建议你了解更多关于指针的知识。

【讨论】:

  • @DeathNet123 我很高兴能帮上忙。了解更多邻接指针。随着时间和你的努力,事情会变得更加清晰。:-)
  • 很好的解释。
【解决方案4】:

您没有将数组作为副本传递。它只是一个指向第一个元素在内存中的地址的指针。

当将数组作为参数传递时,this

void arraytest(int a[])

意思完全一样

void arraytest(int *a)

所以你正在修改 main.js 中的值。然而,在 C 函数中,参数总是按值传递。在数组(变量)的情况下,当作为函数参数传递时,它衰减到指向数组第一个元素的指针。然后像往常一样按值传递指针。

【讨论】:

    【解决方案5】:

    数组是一个特殊的变量。当您将常规变量作为参数传递给函数时,其值将被复制到与该函数相关的局部变量中。

    当您将数组作为参数传递给函数时,数组的第一个元素的地址会被复制到与该函数相关的局部变量中。

    这基本上就是传递常规变量和传递数组给函数的区别。

    不过,您的看法存在一个问题。如果要修改要传递给函数的常规变量,则需要将其地址传递给函数,因此函数应采用指针类型。所以只需使用指针表示法,即int *p,而不是int p[],尽管它们与函数参数等价。

    您的代码应如下所示:

    #include<stdio.h>
    
    void swap(int *x, int *y);
    
    int main(void)
    {
        int x, y;
    
        x = 1;
        y = 2;
    
        swap(&x, &y);
        printf("%d = x \n %d = y", x, y);
    }
    
    void swap(int *x, int *y)
    {
        int temp;
        temp = *x;
        *x = *y;
        *y = temp;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-12
      • 2015-01-05
      • 2018-01-20
      • 1970-01-01
      • 2012-03-02
      • 2011-01-18
      相关资源
      最近更新 更多