As I know address of array a is the address of first element of this array.
void func(int a[])
{
cout << "address in func: " << &a << endl;;
cout << "GT: " << &a[0] << endl;
}
int main ()
{
int a[] = {0,1,2,3};
cout << "address in main: " << &a << endl;
cout << "address in main a[0]: " << &a[0] << endl;
func(a);
}
Output:
address in main: 0x7ffef67d6790
address in main a[0]: 0x7ffef67d6790
address in func: 0x7ffef67d6778
GT: 0x7ffef67d6790
Why address of array a in func() difference with address of a[0]?
Why address of array a in func() difference with address of a[0]?
Because you're calling the function func() passing a by value. This means the a inside the function func() is actually a copy of the original decayed pointer that you're passing to func() from main(). And since they're different variables, they have different addresses. Thus by writing cout << &a; you're printing the address of this separate local variable named a.
If you want to print the original address, you should write inside func():
void func(int a[])
{
//---------------------------------v---------->removed the &
cout << "address in func: " << a << endl;;
cout << "GT: " << &a[0] << endl;
}
Demo
address in main: 0x7ffcfb0a4320
address in main a[0]: 0x7ffcfb0a4320
address in func: 0x7ffcfb0a4320
GT: 0x7ffcfb0a4320
As it has been explained in the comments, you're not passing the "same" variable to your function.
When you're calling your function, it makes a local copy within it of your array of int.
In order not to waste memory, and let's say you upgrade your program and now, you're not passing to your function an array of int but a std::vector which is quite big, we have in C++ arguments passed by references (myType & myVar).
This is the same than passing an argument by pointers in C.
Passing something by reference actually creates an ALIAS to the variable passed. So you'd now have 2 ways to act on the variable : the variable itself in your main program, and the alias in your function.
Obviously, if you do not want to modify it in the function, you can pass it by const reference (const myType & myVar) which is the same than in C with const *.
It is a fallacy inherited from C that
void func(int a[])
would pass an array to the function.
While int a[] looks like an array you can't actually pass an array to a function. An array always decays to a pointer and the pointer is actually what you pass to the function. So the above is equivalent to writing
void func(int *a)
and maybe now you can see why &a, the address of the local pointer, and &a[0] the address of the first element of the array are different.
Related
int q[10]={0};
cout << q << endl;
cout << &q << endl;
cout << &q[0] << endl;
output is
0x7fffd4d2f860
0x7fffd4d2f860
0x7fffd4d2f860
Now when i do this->
int *r=q; // allowed
int *r=&q[0] // allowed
int *r=&q // not allowed
Why is the third assignment not allowed when it is essentially the same thing?
If you have an array declared like
T a[N];
where T is some type specifier then a pointer to the array will be declared like
T ( *p )[N] = &a;
A general rule is the following. If you have a multidimensional array (including one-dimensional arrays) like for example
T a[N1][N2][N3];
then this declaration you may rewrite like
T ( a[N1] )[N2][N3];
To get a pointer to the first element of the array just substitute the content in the parentheses the following way
T ( *p )[N2][N3] = a;
If you want to get a pointer to the whole array then rewrite the declaration of the array like
T ( a )[N1][N2][N3];
and make the substitution
T ( *p )[N1][N2][N3] = &a;
Compare this with a declaration of a scalar object and a pointer to it.
For example
T obj;
You may rewrite the declaration like
T ( obj );
Now to get a pointer to the object you can write
T ( *p ) = &obj;
Of course in this case the parentheses are redundant and the above declaration is equivalent to
T *p = &obj;
As for this code snippet
int q[10]={0};
cout << q << endl;
cout << &q << endl;
cout << &q[0] << endl;
and its output
0x7fffd4d2f860
0x7fffd4d2f860
0x7fffd4d2f860
then array designators used in expressions with rare exceptions are converted to pointers to their first elements.
So in fact the two expression q and &q[0] in these statements
cout << q << endl;
cout << &q[0] << endl;
are equivalent. On the other hand, the address of the array itself is the address of the memory extent that the array occupies. And in the beginning of the extent there is the first element of the array. So the three expressions give the same result: the address of the extent of memory occupied by the array.
Why is the third assignment not allowed when it is essentially the same thing?
Because The C++ language has a feature called "type safety". There is a type system that helps you keep the logic of your program sound.
One particular rule is that arbitrary pointer types can not be used to initialise pointers of other, incompatible types. In this case, you have a pointer to type int (.i.e. int*) that you try to initalise with an expression of type pointer to type array of 10 int (i.e. int(*)[10]). One type is not implicitly convertible to the other, hence the program is ill-formed.
Then why does cout print same things in all of the three cases?
Because all of the pointers have the same value. The first byte of the first element of the array is the same byte as the first byte of the entire array.
It just so happens that the stream insertion operator handles all pointer types1 exactly the same, so pointers with same value but different type produce the same output.
1 Pointers to character types are an exception. They are treated entirely differently.
Why can't we assign address of array to pointer?
Actually, we can assign address of an array to a pointer. We just cannot assign address of a array (or any other object for that matter) to a pointer of wrong type. We need a pointer to an array in this case:
int (*r)[10] = &q;
You cannot do the third assignment because &q's type is an int (*)[10], which is incompatible with the type of int* r.
The output of cout << &q does not reveal the type of &q. See this documentation link.
q is a fixed-length array. Specifying q by itself in an expression decays into a pointer to the 1st element of q. Thus, q decays to the same pointer value that &q[0] returns. &q, on the other hand, returns the memory address of the q variable itself, and for an array, its 1st element occupies that same memory address.
There is an operator<<(void*) defined for std::ostream, and void* can accept (almost) ANY type of pointer. Since all three of your cout calls resolve to the same memory address, and there is an operator<< that accepts all three types of pointers, that is why all three calls print the same number.
As for your assignments:
q is an int[10], which decays into an int*, which is why int *r=q; works.
&q[0] dereferences q to access its 1st element, which is an int, and then takes the address of that element, producing an int*, which is why int *r=&q[0]; works.
since q is an int[10], &q is an int(*)[10], which DOES NOT decay into an int*, which is why int *r=&q; does not work. You would have to declare r using the correct type:
int (*r)[10] = &q;
The following code demonstrates the differences between arr, &arr and &arr[0] where arr is an array of integers.
#include <iostream>
#include <string_view>
// Reference: https://stackoverflow.com/questions/81870/is-it-possible-to-print-a-variables-type-in-standard-c/56766138#56766138
// Type finding code start
template <typename T>
constexpr auto type_name()
{
std::string_view name, prefix, suffix;
#ifdef __clang__
name = __PRETTY_FUNCTION__;
prefix = "auto type_name() [T = ";
suffix = "]";
#elif defined(__GNUC__)
name = __PRETTY_FUNCTION__;
prefix = "constexpr auto type_name() [with T = ";
suffix = "]";
#elif defined(_MSC_VER)
name = __FUNCSIG__;
prefix = "auto __cdecl type_name<";
suffix = ">(void)";
#endif
name.remove_prefix(prefix.size());
name.remove_suffix(suffix.size());
return name;
}
// Type finding code end
int main()
{
int arr[5] = {1, 2, 3, 4, 5};
std::cout << "Value: " << arr << "\tType: " << type_name<decltype(arr)>() << std::endl;
std::cout << "Value: " << &arr << "\tType: " << type_name<decltype(&arr)>() << std::endl;
std::cout << "Value: " << &arr[0] << "\tType: " << type_name<decltype(&arr[0])>() << std::endl;
return 0;
}
See it in action.
Sample Output:
Value: 0x7ffcdadd22d0 Type: int [5]
Value: 0x7ffcdadd22d0 Type: int (*)[5]
Value: 0x7ffcdadd22d0 Type: int*
While all three are associated with the same memory location, they are of different types.
Reference: Is it possible to print a variable's type in standard C++?
This question already has answers here:
Passing Arrays to Function in C++
(5 answers)
What is array to pointer decay?
(11 answers)
Closed 4 months ago.
I'm sorry for my bad English first.
I've encountered a strange problem when coding in 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. And strangely, the difference between them always is 212.
Can anyone explain please? 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. That's what make me think those two &a should be the same. Now I get it, thank you everyone!
Your function declaration
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. 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.
You're passing the a argument by value, so each function has its own copy of it (of the pointer, not the array data). 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
The parameter and the local variable are distinct objects and since their lifetimes overlap, they must have distinct memory addresses.
Please read about pass by value and pass by references.
So what happened here is:
you initialised an array in main function. &a will refer to the address of a.
you passed as a pass by value argument to another 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.
I hope the concept is clear.
Use the following syntax to pass arrays by (const) reference : 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. 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
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.
The both statements will output the same value: the address of the extent of memory occupied by the array.
In this function call
Func(a);
the array designator is implicitly converted to pointer to its first element of the type int( * )[3].
The value of the pointer expression is assigned to the local variable (parameter) a of the function Func.
The function parameter of the pointer type a and the array a defined in main occupy different extents of memory.
If to rename the function parameter as for example
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
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].
So as you can see this statement
cout << static_cast<void *>( &b );
outputs the address of the local variable (parameter) b.
If you want to get the address of the array a within the function Func then you should write
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.
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
010FFD08
010FFD08
010FFD08
As you can see the three values are equal each other.
But if you will write in the function Func
std::cout << static_cast< void * >( &a ) << '\n';
^^^^
you will get the address of the local variable (parameter) a of the function. 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.
I am messing around a little with pointers. Please take a look at the following results (addresses).
1st code:
#include <iostream>
int main(){
int a = 5;
void* pointer = &a;
std::cout << a << std::endl << &a << std::endl;
std::cout << pointer << std::endl ;
std::cin.get();
}
Result:
2nd code:
#include <iostream>
int main(){
int a = 5;
void* pointer = &a;
std::cout << a << std::endl << &a << std::endl;
std::cout << &pointer << std::endl ;
std::cin.get();
}
Result:
Why does the address of the variable a change between the two codes?
In the first case, you never take the address of pointer, so pointer can be stored in a register, or even not at all. (Modern compilers are very clever, and modern machines have many registers.)
For instance, gcc 11 keeps the value in a register without optimization, and with -O2 it just inserts the address of a directly. (Assembly here, for the curious.)
In the second case, you do take the address of pointer, so it must be stored somewhere in memory.
This means that a might be stored in a different place in order to make room for it.
Also, some platforms randomize storage locations in order to make programs less hackable, so it's usually not a good idea to assume that things will have the same address in different "runs".
In the first code poiner stores the address of variable a, and by command.
std::cout<<pointer<<std::endl;
You print the address of a. That's it.
In the second code pointer also stores the address of variable a, but &pointer is the address of variable pointer. Try the following
#include <iostream>
int main(){
int a = 5;
void* pointer = &a;
void** pointer_to_pointer = &pointer;
std::cout << a << std::endl << &a << std::endl << pointer << std::endl;
std::cout << &pointer << std::endl << pointer_to_pointer;
std::cin.get();
}
The output for me is
5
0x7aba1bd92e94
0x7aba1bd92e94
0x7aba1bd92e98
0x7aba1bd92e98
It is very simple.
int a and void* pointer are two distinct variables or I better say memory locations on the stack. a holds a value like 5 in its location. pointer holds the address to a's memory location. pointer itself is stored in a different location and when you write std::cout << &pointer << std::endl; it will print the address of the pointer variable, not the contents of it which is a's address.
As a simplified example:
Consider 0x4 as the address of pointer itself and the value inside it is 0xC. This value points to a's location. In order to read the value of a(which is 5), you first have to go to 0x4 to read its content. Its content is 0xC and now you have successfully found out that a's location is 0xC. Then you have to go to 0xC and at that address, you will find the value 5.
You look at -> 0x4( content == 0xC ) -> 0xC( content == 5 ) -> done!
I thought I understood pointers, but I think there's a nuance by how they're treated differently that I'm not quite following. When I pass an integer pointer or the address of an integer to showInt, it will print out the same memory address as it would outside the function. However. When I pass the following pointer to showChar;
char* value = "One";
showChar(value);
The address of the first element is different inside the function than it is outside the function. I understand that this is behaviour consistent with passing by value, and that a copy of the pointer is made within the function, however I was under the impression that a copy of a pointer still held the same address. Why is it different when dealing with pointers to char? If the char pointer just stores the address of the first element of the string literal, then why would the pointer in the function not point to the same memory location, but instead point to a new area in memory? That suggests to me that it isn't copying a char pointer, but creating a new char pointer and assigning it the value pointed to by the original pointer. If so, I don't understand why.
I understand that you can access the pointer address in the function by passing a pointer-to-pointer, or a reference-to-pointer instead, but why this is the case still confuses me.
Passing a pointer to char;
void showChar(char* name){
cout << name << endl;
cout << &name << endl;
}
Passing a pointer to int;
void showInt(int* num){
cout << num << endl;
cout << *num << endl;
}
The first line in showChar:
cout << name << endl;
will print the contents behind the pointer name, since the IO streams operators in C++ are overloaded to print char-pointers as text instead of the pointer as a number.
With the second line in this function
cout << &name << endl;
you don't print the pointer address name but instead the pointer (address) of the local variable name (which happens to be of a pointer type). That's taking the reference one time too much. What you want is change the behavior of how operator<<(ostream &, char*) works, namely printing the pointer address instead of printing a C-string.
You can do this by simply converting the pointer before passing it to cout, like this:
void showChar(char* name){
cout << (void*)name << endl;
}
Your showChar and showInt functions are printing different things.
In showChar, this:
cout << &name << endl;
prints the address of name, which is a local variable. In showInt, you don't print the value of # rather you print the value of num, which is an address, but not the address of a local variable.
In showChar, if you want to print value of name as an address, you'll need to convert it to some other pointer type such as void*:
cout << (void*)name << endl;
because the overload of operator<< for char* dereferences the char* pointer and prints the C-style string that it points to.
In more detail:
void showChar(char* name){
cout << name << endl; // prints the contents of the string that
// `name` points to
cout << &name << endl; // prints the address of the local variable `name`
}
void showInt(int* num){
cout << num << endl; // prints the value of the pointer `num`
cout << *num << endl; // prints the value of the `int` object that
// `num` points to
}
I know that a function pointer stores the address of a function.
int fun(int x){
//return something
}
int (pfun*)(int)=&fun;
int main(){
std::cout << &fun << "\n"; // this print out 1
std::cout << fun << "\n" ; // this print out 1
std::cout << &pfun << "\n"; // this print out 0x0022ff40
std::cout << pfun << "\n" ; // this print out 1
}
So my questions are :
1) if the fun() doesn't even have an address how can pfun does point to fun().
2) for example in dynamic binding when I use a pointer function at runtime. does the compiler change pfun value to a real pointer like 0X..... so that at runtime will know which function to call since the names doesn't existe after compilation?
The expressions fun and &fun have the same meaning: &fun which is equivalent to the value stored in pfun, so it is no wonder that the three of them yield the same output. &pfun is the address of the pointer, which is the address of the variable.
Now the question is why 1... well, the answer is that there is no overloaded operator<< that takes an std::ostream and a function pointer, so the compiler tries to find the best match among the existing overloads which happens to be bool (a function pointer is implicitly convertible to bool). The function pointer will be converted to false only if the function pointer is null, which is not the case. The true value is finally printed as 1 (you can check this by doing: std::cout << std::boolalpha << fun which will print true).
If you want to obtain the actual address of the function (in this process) you can force the cast to a void pointer and print the result. This might not be technically correct, but it will give you a number different than 1... Note that the value might differ in different runs and basically has no meaning at all.
operator<< does not have an appropriate overload for printing function pointers. Try this instead.
#include <iostream>
void fun() {}
void (*pFun)() = &fun;
int main ()
{
std::cout << (void*)pFun << "\n";
}