This question already has answers here:
C pointer to array/array of pointers disambiguation
(13 answers)
Closed 8 years ago.
I have read the pointer to array c++
and have some experiment on it.
#include <iostream>
using namespace std;
int main()
{
int g[] = {9,8};
int (*j)[2] = &g;
int *i = g;
int n = (*j)[0];
int m = *(i + 0);
cout << "n:" << n << endl;
cout <<"m:" << m << endl;
cout << "=============" << endl;
cout << "*(j):" << *(j) << endl;//9's address ???
cout << "j:" << j << endl;//9's address ???
cout << "&j:" << &j << endl;//what it is???
cout << "&(*j)" << &(*j) << endl;//9's address ???
cout << "=============" << endl;
cout << "*(i):" << *(i) << endl;//get the value pointered by i
cout << "i:" << i << endl;//i's value store g's address
cout << "&i:" << &i << endl; //i's address
cout << "&(*i):" << &(*i) << endl;//9's address
cout << "=============" << endl;
cout << "*(g):" << *(g) << endl;//get the value pointered by g
cout << "g:" << g << endl;//g's value store 9's address
cout << "&g:" << &g << endl;//9's address???
cout << "&(*g):" << &(*g) << endl;//9's address
return 0;
}
The result is :
n:9
m:9
=============
*(j):0x7fff56076bbc
j:0x7fff56076bbc
&j:0x7fff56076bb0
&(*j)0x7fff56076bbc
=============
*(i):9
i:0x7fff56076bbc
&i:0x7fff56076ba8
&(*i):0x7fff56076bbc
=============
*(g):9
g:0x7fff56076bbc
&g:0x7fff56076bbc
&(*g):0x7fff56076bbc
[Finished in 0.3s]
What I want to ask is:
1.Why
int (*j)[2] = &g;
int *i = g;
if I change either one &g to g, or g to &g, it will give a compile error, what is the difference?
(I think that the array name is a pointer, so why cannot I use int (*j)[2] = g and what is the meaning of &g, it is a pointer already, why get address again?)
2.
Since the &g and g, their address are the same, why cannot be exchanged?
3.
Why the &g's value is 9's address? Is it store its own address?
4.
Can you explain the j variable part?
I cannot understand why j stores the 9's address and *(j) gets the 9's address, &(*j) gets the 9's address too?
I am very confused about it now. What I totally understand is about the i variable part,
g variable part is confused about the &g, and the j varialbe part is all confused.
The int (*j)[2] = &g; part is confused too.
You can have a look at this post to understand why g and &g hold the same address:
How array name has its address as well as its first element in it?
The compiler complains when you change either of g to &g because there is a type mismatch. This means that semantically, g and &g have different meanings, even though they may refer to the same thing: g, when used in an expression, decays into pointer to int (int *), but &g is of type pointer to array of 2 ints. These are not compatible types; you can't assign a pointer to an array of ints to something that is a pointer to int (and the same happens the other way around).
Your claim that g is already a pointer is wrong: g is an array. When used in an expression, it decays into a pointer to the array's first element. A pointer is just something that holds an address; an array is an address (the address of its first element). With &g, you get a pointer to an array, you don't get pointer to pointer because arrays do not decay into pointers when the referencing operator is used. Think of it like this: if an array is an address, then applying the "address of" operator - & - yields this same address, which is, by convention, the address of the first element. When you don't apply the & operator, in an expression, the array decays into a pointer to the first element, and then again - it points to the first element, the same address as &g.
g is the variable (in this case array), &g is the address of the variable (in this case the address of the beginning of the array. You might understand that, but the compiler does not, and thus it's giving you an error.
They probably could be exchanged, if you were willing to do type-casting, but that's not a really good idea in this case.
Because g is the array of integers, and the address of the first (0-th) element of that array just happens to be the address of the whole array. Doesn't it make sense?
j in your case is a pointer to the array, of course it is also a pointer to the address with the 0-th element of that array (by definition)
(*j)[2] is pointer to array of 2 integers. In other words it is (almost) equivalent with pointer to pointer to ints. The line int (*j)[2] = g; tries to assign int* to (int**) which is a type mismatch. The line int *i = &g; tries to assign int** to int* which is again a type mismatch.
(I think that the array name is a pointer, so why cannot I use int (*j)[2] = g and what is the meaning of &g, it is a pointer already, why get address again?)
The address of what? In its type checking C++ distinguishes address of variables of different types, so even though int* and int** are both addresses (pointers) they point to different types.
Related
Apologies if this question was already asked, but there are too many questions with C++ arrays and pointers as that I could go through all of them..
Let's say we declare a double array like this:
double val[3] = {-3.1415, 6.2430, +37};
// Declare and initialize pointer variable:
double * pointer = &val[0];
cout << "Elements of the array are: " << endl;
cout << pointer[0] << " " << pointer[1] << " " << pointer[2] << endl;
What confused me is how I get as output the correct values stored in the double array val, without having to use dereferencing operator *, so for example *pointer[0]..
pointer points at the first double in an array of packed doubles.
pointer[1] means *(pointer+1) in a ridiculously fundamental way, so much so that 1[pointer] works. (don't do that btw)
If you have an array of data, then adding 1 to a pointer to the first element gets a pointer to the second.
I have this program:
#include <iostream>
#include <conio.h>
#include <string.h>
using namespace std;
int main()
{
char char1[30] = "ExtraCharacter", char2[30] = "Character", *p;
p = strstr(char1, char2);
cout << "p: " << p << endl;
cout << "char1: " << char1 << endl;
cout << "(p-char1): " << (p-char1) << endl;
return 0;
}
When I run it, I get:
p: Character
char1: ExtraCharacter
(p-char1): 5
as expected.
But this is not the problem, I'm not sure why "Character" - "ExtraCharacter" is an integer (5)? Perhaps not an integer, but a number/digit anyways.
Actually I don't understand why is "Character" stored in p, and not the memory address.
If I understood well from a book, strstr() returns a memory address, shouldn't it be more like a strange value, like a hex (0x0045fe00) or something like that? I mean, it's cout << p not cout << *p to display the actual value of that memory address.
Can someone explain me how it works?
P.S.: I apologize if the title is not that coherent.
But this is not the problem, I'm not sure why "Character" - "ExtraCharacter" is an integer (5)?
You subtract one pointer from another and result - number, distance from char char1 points to to char p points to. This is how pointer arithmetic works.
Note: this subtraction is only valid when both pointers point to the same array (or behind the last element), which is the case in your code, but you need to be careful. For example if strstr() does not find susbtring then it would return nullptr and your subtraction will have UB. So at least check p before subtracting (and passing nullptr to std::cout would have UB as well)
If I understood well from a book, strstr() returns a memory address, shouldn't it be more like a strange value, like a hex (0x0045fe00) or something like that? I mean, it's cout << p not cout << *p to display the actual value of that memory address.
Yes p is a pointer aka memory adress. std::ostream has special rule how to print pointers to char - as strings, because strings in C stored that way. If you want to see it as a pointer just cast it:
std::cout << static_cast<void *>( p );
then you will see it as an address.
To display address, you have to cast char* to void*:
std::cout << "p: " << static_cast<const void*>(p) << std::endl;
Demo
For std::basic_ostream (type of cout), character and character string arguments (e.g., of type char or const char*) are handled by the non-member overloads of operator<< which are being treated as strings. char[30] will be decayed to const char* argument and basic_ostream will output the null terminated string at the address of the pointer.
As for (p-char1), the result of subtracting two pointers is a std::ptrdiff_t. It is an implementation-defined signed integer. That's why the output is 5
I have the following code:
#include <iostream>
using namespace std;
int main()
{
int g[] = {9,8};
int (*j)[2] = &g;
cout << "*(j):" << *(j) << endl;
cout << "j:" << j << endl;
cout << "&j:" << &j << endl;
cout << "&(*j)" << &(*j) << endl;
cout << "*(*j):" << *(*j) << endl;
return 0;
}
which ouputs:
*(j):0x7fff5ab37c7c
j:0x7fff5ab37c7c
&j:0x7fff5ab37c70
&(*j)0x7fff5ab37c7c
*(*j):9
I think that j is a pointer to an array of two integer.
And &g is the address of the whole array.
Then j store the address of the whole array.
And so I use the *(j), it will dereference the first element in the array.
But the result said that *(j) store the array address the same value as j.
I cannot figure out how this happened.
I think that j is a pointer to an array of two integer.
And &g is the address of the whole array.
That is correct.
And so I use the *(j), it will dereference the first element in the array.
This is not. *j gives you the array itself. When you insert it to cout, it decays to a pointer again (this time to a pointer to its first element, type int*) and its value is printed.
It's in effect the same as if you wrote cout << g.
"I think that j is a pointer to an array"
Yes, it is. And that's also the reason why *j output the same address as outputting g would do. In this case an array decays into the pointer and that's why even outputting j yields the same result.
The fact that the same address is outputted might make you think that j and *j are the same pointers, however they are not. Their type is different (a fact that actually matters):
int g[] = {9,8}; // int[]
int (*j)[2] = &g; // int (*)[2]
so using *j becomes equivalent to using g directly, just like *(*j) becomes equivalent to *g.
And &(*j) is nothing but j, which is initialized with an address of an array (an address taken from decayed g, i.e. an address of the first element of this array).
So why j and *j outputs the same address and *(*j) outputs the value of first element?
Because of the type of j being int (*)[2]. A simple example:
int g[] = {9,8};
int (*j)[2] = &g; // j points to the first element as well
cout << *((int*) j);
outputs 9.
int arr[][3] = {{1,3},{2,3},{6,7}};
cout << arr[0] << endl; // W/O col' somehow give you the address, not the element.
cout << arr[0][0] << endl;
I am curious as to why arr[0] prints the address, not the element.
It seems like somehow it's ignoring its dereference operator.
I'd be appreciated if you could help me in terms of a pointer or in depth.
Thank you.
Since arr is a two-dimensional array, arr[0] will give you an entire row (more precisely, the address of that row).
More precisely, since arr is of type int[][3] arr[0] is of type int[3], which decays to int *. Hence, cout << arr[0] << endl; prints a pointer.
array[0] holds the address of the array[0][0...n-1] values so only cout << arr[0]; prints the address since arr[0] is the pointer to the values in arr[0][0..n-1]
If you want specific value of an two dimensional array then you need to give both x and y index like
array[0][0] ... array[0][n-1]
I have the following code:
#include <iostream>
using namespace std;
int main()
{
int g[] = {9,8};
int (*j)[2] = &g;
cout << "*(j):" << *(j) << endl;
cout << "j:" << j << endl;
cout << "&j:" << &j << endl;
cout << "&(*j)" << &(*j) << endl;
cout << "*(*j):" << *(*j) << endl;
return 0;
}
which ouputs:
*(j):0x7fff5ab37c7c
j:0x7fff5ab37c7c
&j:0x7fff5ab37c70
&(*j)0x7fff5ab37c7c
*(*j):9
I think that j is a pointer to an array of two integer.
And &g is the address of the whole array.
Then j store the address of the whole array.
And so I use the *(j), it will dereference the first element in the array.
But the result said that *(j) store the array address the same value as j.
I cannot figure out how this happened.
I think that j is a pointer to an array of two integer.
And &g is the address of the whole array.
That is correct.
And so I use the *(j), it will dereference the first element in the array.
This is not. *j gives you the array itself. When you insert it to cout, it decays to a pointer again (this time to a pointer to its first element, type int*) and its value is printed.
It's in effect the same as if you wrote cout << g.
"I think that j is a pointer to an array"
Yes, it is. And that's also the reason why *j output the same address as outputting g would do. In this case an array decays into the pointer and that's why even outputting j yields the same result.
The fact that the same address is outputted might make you think that j and *j are the same pointers, however they are not. Their type is different (a fact that actually matters):
int g[] = {9,8}; // int[]
int (*j)[2] = &g; // int (*)[2]
so using *j becomes equivalent to using g directly, just like *(*j) becomes equivalent to *g.
And &(*j) is nothing but j, which is initialized with an address of an array (an address taken from decayed g, i.e. an address of the first element of this array).
So why j and *j outputs the same address and *(*j) outputs the value of first element?
Because of the type of j being int (*)[2]. A simple example:
int g[] = {9,8};
int (*j)[2] = &g; // j points to the first element as well
cout << *((int*) j);
outputs 9.