简体   繁体   English

main() 和 function() 中 &array 的不同值

[英]Different value of &array in main() and in function()

I'm sorry for my bad English first.首先我很抱歉我的英语不好。 I've encountered a strange problem when coding in C++.我在 C++ 中编码时遇到了一个奇怪的问题。

using namespace std;

void Func(int a[2][3])
{
   cout <<(int) &a;
}

int main()
{
   int a[2][3] =
   {
       {1,2,3},
       {4,5,6}
   };
   cout << (int)&a << endl;
   Func(a);
   return 0;
}

I was confused that &a in main() and in function Func() returned different values.我很困惑 main() 和 function Func() 中的 &a 返回不同的值。 And strangely, the difference between them always is 212. Can anyone explain please?奇怪的是,它们之间的区别总是212。有人能解释一下吗? Thank you for your help.谢谢您的帮助。

P/s:Thank you all for your answer.My teacher says that C++ doesn't allow passing an array by value, because if the array has 1 million elements, that would decrease the performance a lot only for copying all of them, so he says only pass by reference is allowed. P/s:谢谢大家的回答。我的老师说 C++ 不允许按值传递数组,因为如果数组有 100 万个元素,那么仅复制所有元素就会大大降低性能,所以他说只允许通过引用。 That's what make me think those two &a should be the same.这就是让我认为这两个 &a 应该相同的原因。 Now I get it, thank you everyone!现在明白了,谢谢大家!

Your function declaration您的 function 声明

void Func(int a[2][3])

is completely equivalent and interchangeable with:与以下内容完全等效并可互换:

void Func(int (*a)[3]).

As you can see, you are passing a pointer to an array of three ints by value .如您所见,您正在通过value传递一个指向三个 int 数组的指针。 Therefore the address of the local function parameter is different from the address of the variable in main, even if they may hold the same value.因此,局部 function 参数的地址与 main 中变量的地址不同,即使它们可能持有相同的值。

You're passing the a argument by value, so each function has its own copy of it (of the pointer, not the array data).您正在按值传递a参数,因此每个 function 都有自己的副本(指针的副本,而不是数组数据的副本)。 The constant offset you're seeing comes from the distance between the stack frames of the two functions, and this is constant.您看到的恒定偏移量来自两个函数的堆栈帧之间的距离,这是恒定的。

If you change the function to get a reference to the array ( void Func(int (&a)[2][3]) you will get the same value in both cases如果您更改 function 以获取对数组的引用( void Func(int (&a)[2][3])您将在两种情况下获得相同的值

The parameter and the local variable are distinct objects and since their lifetimes overlap, they must have distinct memory addresses.参数和局部变量是不同的对象,由于它们的生命周期重叠,它们必须具有不同的 memory 地址。

Please read about pass by value and pass by references.请阅读按值传递和按引用传递。 So what happened here is:所以这里发生的是:

  1. you initialised an array in main function.您在main function 中初始化了一个数组。 &a will refer to the address of a . &a将引用a的地址。
  2. you passed as a pass by value argument to another function.您作为值传递参数传递给另一个 function。 A copy of a is created to be consumed in Func and &a will refer to the memory location of a local to Func .创建 a 的副本以在Func中使用, &a a引用Func本地的 memory 位置。

I hope the concept is clear.我希望这个概念是清楚的。

Use the following syntax to pass arrays by (const) reference: const int (&a)[2][3]使用以下语法通过 (const) 引用传递 arrays: const int (&a)[2][3]

#include <iostream>

void func(const int (&a)[2][3])
{
    for (const auto& row : a)
    {
        for(const auto& value : row )
        {
            std::cout << value << " ";
        }
        std::cout << "\n";
    }
}

int main()
{
    int a[2][3] =
    {
        {1,2,3},
        {4,5,6}
    };

    func(a);

    return 0;
}

This is because C rules on how pointers and arrays work are a little weird.这是因为 C 关于指针和 arrays 工作方式的规则有点奇怪。 You're actually taking the address of a pointer to the array, not the actual address of the array.您实际上是在获取指向数组的指针的地址,而不是数组的实际地址。 If you want to get the address to the array you need to take the address of the first element instead:如果要获取数组的地址,则需要取第一个元素的地址:

&a[0]

For starters it is a bad idea to cast an address to the type int like对于初学者来说,将地址转换为 int 类型是一个坏主意

cout << (int)&a << endl;

you could just write你可以写

cout << static_cast<void *>( a ) << endl;

or或者

cout << static_cast<void *>( &a ) << endl;

Or even like甚至喜欢

cout << a << endl;
cout << &a << endl;

though with static_cast the code looks more readable.尽管使用static_cast代码看起来更具可读性。

The both statements will output the same value: the address of the extent of memory occupied by the array.这两条语句将 output 的值相同:memory 所占用的数组的地址范围。

In this function call在这个 function 通话中

Func(a);

the array designator is implicitly converted to pointer to its first element of the type int( * )[3] .数组指示符被隐式转换为指向其类型int( * )[3]的第一个元素的指针。

The value of the pointer expression is assigned to the local variable (parameter) a of the function Func .指针表达式的值被赋值给 function Func的局部变量(参数) a

The function parameter of the pointer type a and the array a defined in main occupy different extents of memory.指针类型a的function参数和main中定义的数组a占用memory的不同区。

If to rename the function parameter as for example如重命名function参数如

void Func(int b[2][3])

to distinguish it from the array with the same name defined in main then you may imagine the function call the following way为了将它与 main 中定义的同名数组区分开来,您可以想象 function 调用以下方式

Func(a);功能(一);

//...

void Func( /*int b[2][3] */ )
{
   int ( *b )[3] = a;
 
   cout << static_cast<void *>(  &b );
}

Pay attention to that the function parameter declared as having the array type int[2][3] is implicitly adjusted by the compiler to pointer to the array element type that is int ( * )[3] .请注意,声明为具有数组类型int[2][3]的 function 参数被编译器隐式调整为指向数组元素类型int ( * )[3]的指针。

So as you can see this statement所以你可以看到这个声明

   cout << static_cast<void *>(  &b );

outputs the address of the local variable (parameter) b .输出局部变量(参数) b的地址。

If you want to get the address of the array a within the function Func then you should write如果你想在 function Func中获取数组a的地址,那么你应该写

   cout << static_cast<void *>(  b );

In this case the addresses outputted in main and in the function will coincide because the parameter b stores the address of the first element of the array a .在这种情况下, main 和 function 中输出的地址将一致,因为参数b存储数组a的第一个元素的地址。

Here is a demonstration program.这是一个演示程序。

#include <iostream>

void Func( int a[2][3] )
{
    std::cout << static_cast< void * >( a ) << '\n';
}

int main()
{
    int a[2][3] =
    {
        {1,2,3},
        {4,5,6}
    };

    std::cout << static_cast<void *>( a ) << '\n';
    std::cout << static_cast<void *>( &a ) << '\n';

    Func( a );
}

The program output might look like程序 output 可能看起来像

010FFD08
010FFD08
010FFD08

As you can see the three values are equal each other.如您所见,这三个值彼此相等。

But if you will write in the function Func但是如果你会写在 function Func

    std::cout << static_cast< void * >( &a ) << '\n';
                                       ^^^^

you will get the address of the local variable (parameter) a of the function.您将获得 function 的局部变量(参数) a的地址。 It is evident that this address differs from the address of the extent of memory occupied by the array because for the parameter a there was allocated a separate extent of memory the size of which is equal tp the value of the sizeof( int( * )[3] ) and usually this value is equal to 4 or 8.很明显,该地址与数组占用的 memory 范围的地址不同,因为对于参数 a,分配了一个单独的 memory 范围,其大小等于 tp 的值sizeof( int( * )[3] ) ,通常这个值等于 4 或 8。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM