为什么函数要对实际参数的副本进行操作?

我想了解将值按参数传递给函数时发生的情况。这个“函数复制值”如何完成?

我希望这是传递数组与传递两个变量之间的平行点。

我搜索了一些线程,尽管我还有其他疑问,我认为this最适合。

这里有两个例子:

Ex1:

void function(int arr[])
{
    cout << arr << endl;                // The address of the first elm
    cout << sizeof(arr);                // 4 (bytes size of address on 32 bit)
}

int main()
{
    int vector[] = {1,2,3,4,5,6,7};
    function(vector);
    return 0;
}

Ex2:

void interChange(int a,int b)
{
    int tmp;
    tmp = a;
    a = b;
    b = tmp;
}

int main()
{
    int a = 5,b = 3;
    interChange(a,b);
    return 0;
}

在第一个示例中,我想表明即使我通过值传递数组,它仍然被解释为指针(允许修改功能以更改实际的vector值),这就是为什么打印数组将输出一个地址,打印其大小将输出指针的尺寸。

在第二个示例中,参数按值传递,但是这一次它们不更改变量ab的值。这个过程如何进行?为什么要复制它们而不使用地址?编译器是否考虑到有关其地址的某些信息?如果我先在&a中打印main(),然后在interChange内打印,则会得到两个彼此非常接近的地址,例如:0x69fed80x69fe80

coffee3582 回答:为什么函数要对实际参数的副本进行操作?

查看何时将任何参数传递给任何函数,通常会将其复制到函数参数。但是这是数组情况下的例外,这种情况不会发生。 每当将数组传递给任何函数时,编译器都会自动将其转换为指向数组第一个元素的指针。 现在让我们来看看两种情况

情况1:传递数组时,编译器将其转换为指向该数组第一个元素的指针。现在是一个int类型的数组,因此Ofc指针将具有int类型,并且int指针的大小为4个字节,您可以看到。

情况2:在第二个函数中传递了两个int时。传递的参数将复制到function参数。因此,请记住您是否在参数和参数列表中写的名称与以前相同。两者都是不同的变量。您在函数中所做的任何事情都不会影响main中的变量。因此,您的交换函数没有用,因为它正在处理其自身函数的A和B,而不是在主函数的最后。

我希望现在明白了。如果您没有参与,请发表评论

,

好的,这只是C编程语言选择的约定。 C ++从C继承了它。

您给出了两个不同但有些相关的示例。我将分别解决它们。

对于第二个示例: 例如,当您声明变量int a时-机器需要将值存储在某个地方。那就是分配了一定数量的RAM来存储可以解释为int的值。在x86(32位计算机)上-这应该是32位/ 4字节的内存。

使用参数调用函数时-值必须传递给函数。必须分配一些内存来存储此值。 C和C ++默认选择复制值。这就是调用函数时发生的第一件事-分配了一些内存。其参数和值将复制到该新内存。这对于int很有效,因为它们可以存储在大小有限的CPU寄存器中。如果要修改值-您需要获取存储值的内存地址-将该地址传递给函数。请注意,您已复制了地址。但是具有地址-指针-可以更改存储在该地址的值。


// Copy two integers
void interChange(int a,int b) {
    int tmp;
    tmp = a;
    a = b;
    b = tmp;
}

void interChangePtr(int* a,int* b) {
    int tmp;
    tmp = *a;
    a* = *b;
    b* = tmp;
}

int main() {
    int a = 5,b = 3;
    interChange(a,b);
    // a=5,b=3.

    interChangePtr(&a,&b);
    // a=3,b=5

    return 0;
}

对于您的第二个示例-这是C选择的另一种约定。当您键入:

int main() {
 int arr[25]; // Allocates memory on the stack for 25 integers
 ...

声明一个数组(C风格)会通知编译器您希望它为堆栈上的数组分配内存。数组只是一块连续的内存。因此,您可以使用指向它的指针并使用该指针修改值。在C中,如果您键入arr-这是指向在堆栈上为您分配的内存的指针。因此,当您以void function(int arr[])的形式调用函数function(arr)时-实际上会将指针传递给数组,而不是实际的内存块。 这些约定的原因-是性能。将单个指针传递给数组然后分配新数组并复制数据的速度更快。

希望为您提供一些进一步研究该主题的指针。

,

按值复制实际上意味着以下模式。

int a = 10;
int b = a;

在这个简单的示例中,a的值被复制到变量b中。

第一个示例中的此函数声明

void function(int arr[]);

等同于声明

void function(int *arr);

因为编译器会隐式地将具有数组类型的参数调整为指向数组元素类型的指针。

另一方面,按值传递的数组将隐式转换为指向其第一个元素的指针。

此函数定义

void function(int arr[])
{
    cout << arr << endl;                // The address of the first elm
    cout << sizeof(arr);                // 4 (bytes size of address on 32 bit)
}

及其呼叫

function(vector);

您可以想象以下方式

function(vector);
//...

void function( /*int arr[] */)
{
    int *arr = vector; 
    cout << arr << endl;                // The address of the first elm
    cout << sizeof(arr);                // 4 (bytes size of address on 32 bit)
}

那是函数参数是它的局部变量,如果参数通过值传递,那么这些局部变量将获得参数值的副本。

但是请注意,实际上数组的元素是通过引用通过指向数组第一个元素的指针传递的。

它看起来与您具有以下功能的方式相同

void interChange(int *a,int *b)
{
    int tmp;
    tmp = *a;
    *a = *b;
    *b = tmp;
}

interChange( &a,&b);

要显示与传递数组作为参数转换为指向其第一个元素的指针的相似性,可以按以下方式重写函数定义

void interChange(int *a,int *b)
{
    int tmp;
    tmp = a[0];
    a[0] = b[0];
    b[0] = tmp;
}

这就像传递给每个仅包含一个元素的函数数组一样。

本文链接:https://www.f2er.com/3133257.html

大家都在问