C++: Pointers in 2D-arrays are confusing - c++

Can someone explain to me what is going on here? Consider the code
#include <iostream>
int main()
{
int A[2][2] = {{0}};
std::cout << A << std::endl; // First stdout line
std::cout << *A << std::endl; // Second stdout line
std::cout << *(*A) << std::endl; // Third stdout line
}
(Try the code here!)
It seems to me that A should be an array of 2 pointers to arrays, each of which should contain 2 pointers to ints. However, when running the code, the following is written to stdout:
0x7a665507cf80
0x7a665507cf80
0
To me, this makes it seem like the memory address of the first element in A (printed on the first stdout line) is the same as the memory address of the first element in *A. How is this possible, considering that A and *A are clearly two different arrays (since dereferencing A and *A gives different results)?
An alternative interpretation of the output is that the memory address 0x7a665507cf80 either contains the value 0x7a665507cf80 (i.e. a pointer located on that position—in this case A—points to itself) or 0, depending on if it is accessed from A or *A, which also doesn't really make sense to me.

int A[2][2] = {{0}}; This is a static 2D array, it's not a pointer to pointer, it's just a 1D array with special access.
The fact that it's not a point to pointer, but a 2D array on a 1D array means that A[0] or *A accesses the array and returns the 1D array that is the first row. Then the second dereferentiation gets the actual value. This generalizes to nD if you have int A[x][y][z][t]....
So the first two are the "same" address, but they are not the same type.

Related

Use the new operator to allocate an array of integers using the parameter as the size of the array within a function

I've been stuck on this problem and I'm hoping someone can explain where I'm wrong on this. I'm working on an assignment where I need to:
1) Allocate an array that can contain 100 int values by calling allocIntArray and assign the returned pointer to ptr1.
2) Use the new operator to allocate an array of integers using the parameter as the size of the array.
3) Return the pointer that is returned by the new operator.
4) Print out the new array.
I'm trying to print out the array after passing the size I want through the function.
int main() {
int *ptr = NULL;
ptr1 = *allocIntArray(100);
cout << ptr1 << endl;
return 0;
}
//The function I want to call
int *allocIntArray(int size) {
int *newarr = nullptr;
newarr = new int[size];
return newarr;
}
However when I call the function, the output comes out as 00F011E8.
I'm currently trying to understand why this is the output and not the first value in the array. (Just the number 1)
I've been having a lot of trouble grasping pointers any help understanding would be greatly appreciated.
Thanks to everyone who took the time to respond.
From what I understand from assignment directions, I shouldn't need to use vectors. I'm trying to modify my current code to display the array output and this is what currently comes up when I run it.[enter image description hereMy current results
At first, if you're using C++, you should use std::vector/std::array. This avoids a huge amount of possible problems.
It would look like:
#include <iostream>
#include <vector>
int main()
{
// create array of size 10 and initialize it with 0's
std::vector<int> vec(10, 0);
// print array
for(auto a : vec)
std::cout << a << '\t';
std::cout << std::endl;
}
If it's some kind of exercise, you have done four big mistakes:
you dereference the returned pointer to the array. So you get the value of the first element in the array and not the array itself. Simply remove the *.
you print out the address of the first element of the array. To print the array, you have to iterate over each element of the array. This can be done in a for loop:
for(int i = 0; i < 10; ++i)
std::cout << ptr1[i] << '\t';
you want to print out the array uninitialized. In fact, you try to print out some random values which are there in the memory. At first, you have to assign the elements values.
you forget to delete the array by using
delete[] ptr1;
I just have to answer as you seem to be missing some important fundamentals. Either the instructor should be dismissed or you have not paid enough attention in the class. So...
ptr1 = *allocIntArray(100);
You could not have pasted code that compiles, ptr1 is not declared.
You need to understand what the * operator does. What ever value to the right of * must be a pointer. What a pointer is should be fundamental in your understanding. If you had:
int* ptr1 = *allocIntArray(100);
You should have gotten a compiler error, so you must have:
int ptr1;
Somewhere along the line. As allocIntArray(...) returns a pointer, then *allocIntArray(...) gives you an integer.
You would have wanted to:
int* ptr1 = allocIntArray(100);
To get a pointer to the new array. Then you:
std::cout << ptr1 << std::endl;
So, what is ptr1? If it is a pointer then all you are doing is printing the pointer value. Per your stated problem, I'd say ptr1 is in fact a pointer. std::cout has not facility to work with a pointer as you expect. At that, it would have no way of determining the size of your array.
You would want to (And it hurts my fingers to write like this):
for(size_t i= 0; i < 100; ++i)
std::cout << ptr1[i] <<" ";
But!!!
4) Print out the new array.
So what will it print? There was never an instruction to initialize the array. It will print out what ever garbage is sitting in the array when it was created.
Side note, that the instructor has you doing a:
using namespace std;
Says much, as he/she should never have allowed it.

C++ array as parameter reference by default?

forgive me for asking such a simple question, but I couldn't connect the dots from previous answers on SO or other sites. I have read that arrays are passed by reference by default and elsewhere I have read that arrays decay to pointers when passed into functions. I am trying to pass an array to a function and modify it, but cannot reconcile the previous two statements. I am not sure whether I am passing in a pointer or reference to toBin and whether it even matters. The following code is my attempt at making changes to the b array in the toBin function.
When I print the modified array, I get a whole bunch of unexpected text much bigger than the original allocated array of size 11 eg 1000000000 submarine blahblahblah. My expected output is 1000000000.
void toBin(int x,char a[]){ //passed by reference by default
std::cout << a << std::endl;
for (int i=9;i>=0;i--){
if(pow(2,i)<=x){
x=x-pow(2,i);
a[9-i]='1'; //i-1 because char b[] is zero indexed
};
}
}
int main()
{
char c[]="submarine";
double combination = pow(2,sizeof(c)-1);
char b[11]={'0','0','0','0','0','0','0','0','0','0'};
toBin(512, b);
for (int i=0;i<combination;i++){
std::cout << *(b+i) << std::endl;
}
}
Basically you pass everything to the function well. Thing that broke your output it's loop itself.
double combination = pow(2,sizeof(c)-1);
...
for (int i=0;i<combination;i++){
std::cout << *(b+i) << std::endl;
}
Your combination variable can have value like 2^8. So you point by*(b+i) to the address going far beyond the allocated array. To repair it you need change your loop to that:
for (int i=0;i< sizeof(b);i++){

how to Understand complicated array declaration pointers, and &

Here are two lines of code:
int (*parry)[10] = &arr // Line # 1
int *(&arrRef)[10] = ptrs // Line # 2
Line # 1:
parry is a pointer that points to an int array of size 10.
So does it mean:
parray[1] points to the address of arr,
parray[2] points to address of arr
...
parray[10] points to address or arr?
When would I use Line # 1?
Solution:
#include <iostream>
int main(
{
int arr[10] = { 3, 54 };
int (*parry)[10] = &arr;
std::cout << (*parry)[0] << " " << (*parry)[1] << " " << (*parry)[3] << " " << parry[4] << std::endl;
return 0;
}
Output:
3, 54, 0, hex address of arr at index 4.
It seems like what inside parry[0] is a pointer that points to arr associated with the index. So, parry[0] ---> arr[0].
Line # 2:
arrRef is a reference to an int array of size ten pointers. arrRef is referred to by ptrs.
So does it mean:
arry[1] is an int pointer? ...
arry[10] is an int pointer?
What example can this been used in?
When in doubt, see the Clockwise/Spiral Rule.
int (*parry)[10] = &arr;
parry is a pointer to an array of 10 ints.
int *(&arrRef)[10] = ptrs;
arrRef is a reference to an array of 10 pointers to int.
Example:
int main()
{
int arr[10];
int* ptrs[10];
int (*parry)[10] = &arr;
int *(&arrRef)[10] = ptrs;
}
Now I've cleaned up your question, I can see it wasn't what I originally thought. You say:
parray is a pointer that points to an int array of size 10
so clearly you figured out the clockwise/spiral/cdecl stuff already.
So does it mean: ... parray[10] points to address of arr
Firstly, arrays in C++ are indexed starting from zero, so you can access arr[0] .. arr[9] if there are 10 elements; arr[10] would be the eleventh, so is out of bounds.
Now, let's take your sentence apart:
parray is a pointer
right, it isn't an array, it's a pointer. Now, let's consider what it is a pointer to:
an int array of size 10
ok, if it points to that, then *parray must be (a reference to) the original array.
So, (*parray)[0] is the first element of the array, etc.
Note that you can easily test your intuition about all this by just printing things out, and seeing what you get. You'll either see pointers, and be able to compare the addresses, or you'll see integer values, or you'll get (hopefully informative) compile errors. Try it out!
Oh, and:
When would I use line 1?
Only if you need to re-seat it, in general. For example, if you want to choose one of two different arrays based on some logic, and then ... perform further logic on whichever was selected.
Next, you said
arrRef is a reference to an int array of size ten pointers.
Correct!
arrRef is refer to by ptrs
No, arrRef refers to an array, the array has size 10, and its 10 elements are pointers-to-int. Note this is not the same type as the first array!
Since references can be used with the same syntax as the thing they refer to, we can use arrRef as an array.
So, arrRef[0] is the first element of the array, and it is a pointer-to-int.
What example can this been used in?
The only common reason for using reference-to-array is to avoid pointer decay, allowing templates to deduce the number of elements.
I think that in this statement
//line1// int (*parry)[10] = $arr
^^^ ^^
there is a typo
There must be
//line1// int (*parry)[10] = &arr;
^^^ ^^
It is assumed that arr is an array of type int[10]. For example
int arr[10];
And this declaration
int (*parry)[10] = &arr;
declares a pointer to this entire array.
As for this declaration
//line2// int *(&arrRef)[10] = ptrs;
^^^
then it is assumed that ptrs is an array of type int *[10] That is elements of the array have type int *. They are pointers.
And this declaration
int * (&arrRef)[10] = ptrs;
declares a reference to this array. A reference is in fact is an alias of an array.
In C++ 2014 you could define a reference to an array simpler.
For example
decltype( auto )arrRef = ( ptrs );
Here is a demonstrative program
#include <iostream>
int main()
{
int a[10];
decltype( auto )ra = ( a );
std::cout << sizeof( a ) << std::endl;
std::cout << sizeof( ra ) << std::endl;
ra[0] = 10;
std::cout << a[0] << std::endl;
std::cout << ra[0] << std::endl;
}
The program output is
40
40
10
10
For parsing C declarations it is valuable to remember, in the words of Kernighan and Ritchie, that "the syntax is an attempt to make the declaration and the use agree" (K&R, TCPL, 5.12). In other words, you can treat a declaration as an expression and simply apply the operators in the proper order. That will show you what type the declared identifier must have.
For example, in int (*parry)[10] you first apply the * operator, because it is in parentheses. This indicates that parray is a pointer. Then you apply the [] operator, indicating that the result of the dereferencing was an array; the 10 indicates the number of elements. The obtained element is of type int. Summing up: parray was a pointer to an array of int.
Declarations of references in C++ can not be solved that way because there is actually no operator which would create a reference, or dereference one; both operations are implicit in C++. The & symbol is used to signify references in declarations only (perhaps somewhat confusingly, because in expressions it's used to take an address). But if you think of the & in declarations as a * substitute to signify a reference instead of a pointer you should still be able to parse any declaration.

Pointer of array, where does the information of memory space of each element of that array store?

For example:
int *p;
int a[2] = {1, 2};
p1 = a;
I was wondering where does c++ store the information of memory space of each element? I mean, when I do this:
cout << p << endl;
I only can get the memory address of that array, there is obviously no information related to the "memory length" of single element. But I think there should be some place that the language can refer to the space of memory space of each element. Since if I go on the call this:
cout << *++p << endl;
I can get the second element of that array no matter what type of element in that array and the corresponding space of memory of single element. The language is able to automatically kind of jump over the certain space memory to get the right start place of the next element and its address.
So, again, my question is: Where is the information of the memory space of element in that array stored? Or is there something like "\0" at the end of each element to signify the end of one element in that array, so the *++p is about to get to the next right place?
where does the information of memory space of each element of that array store?
When you use:
int *p;
int a[2] = {1, 2};
p = a;
memory for the elements of a are in the stack. They memory is contiguous. p points to the first element of a.
Regarding:
I can get the second element of that array no matter what type of element in that array and the corresponding space of memory of single element. The language is able to automatically kind of jump over the certain space memory to get the right start place of the next element and its address.
Yes, that is correct.
From a purely numerical point of view,
p+1 == p + sizeof(*p)
sizeof(*p) can be computed at compile time. There is no need for any run time information. There is no need for markers to signify the end of an element.
The memory in an array is contiguous, so yes incrementing a pointer will get you from one element to the next element.
The way that it knows how far in memory to go to get to the next element is by the type of the pointer, in this case it is an int*, so it knows to increment by sizeof(int) to get to the next element.
It doesn't. C++ has no runtime information about the types of variables. It simply interprets the data behind the pointer as the type you gave to it in your source code. Take the following code for example:
void f(int *) { std::cout << "Integerpointer" << std::endl; }
void f(char *) { std::cout << "Charpointer" << std::endl; }
int i = 9;
int * p = &i;
f(p);
This will print Integerpointer because the compiler knows at compile time that the type of p is int *. The following code will print Charpointer because the type is changed (the compiler interprets the pointer different):
void f(int *) { std::cout << "Integerpointer" << std::endl; }
void f(char *) { std::cout << "Charpointer" << std::endl; }
int i = 9;
int * p = &i;
f(reinterpret_cast<char *>(p));
The compiler substitutes f() with the matching function call in your source code. So the interpretation of the underlying data is done at compiletime.
To address your array question:
The compiler knows the sizes of the elements at compile time. It then adjusts the pointer addition when accessing the elements and puts the size hard coded in your machine code. If you know a bit assambly you can look at the assambly code and see this effect.

Why is it a compile error to assign the address of an array to a pointer "my_pointer = &my_array"?

int my_array[5] = {0};
int *my_pointer = 0;
my_pointer = &my_array; // compiler error
my_pointer = my_array; // ok
If my_array is address of array then what does &my_array gives me?
I get the following compiler error:
error: cannot convert 'int (*)[5]' to 'int*' in assignment
my_array is the name of an array of 5 integers. The compiler will happily convert it to a pointer to a single integer.
&my_array is a pointer to an array of 5 integers. The compiler will not treat an array of integers as a single integer, thus it refuses to make the conversion.
&my_array is the address at which the value of my_array is stored, i.e., it is the address of the address of the array and has type int**.
This would be a fascinating topic for research on neuroscience, semantics, and software development. Even though we can explain the difference between my_array and &my_array, and even though we can repeat the mantra that "arrays are (or are not) pointers", this distinction is still confusing.
Usually when we take the address of something with the "&" operation, we arrive at a completely different value.
int x;
x=5;
cout <<x << " "<<&x<<endl;
First of all, let's challenge this intuition. A pointer can be accidentally equal to the value it is pointing at:
int* x;
x=(int*)(&x);
cout <<"same: "<<x << " "<<&x<<endl;
So in some contexts semantically different things can evaluate to the same thing. But just because two expressions are equal in the current context does not mean that they are interchangeable.
int w=3;
int* ip=&w;
void* vp=&w;
cout <<"Equal: "<<ip<<" "<<vp<<" "<<(ip==vp)<<endl;
cout <<"But not interchangeable: "<<ip+1<<" "<<vp+1<<" "<<(ip+1==vp+1)<<endl;
The same happens with pointers to arrays. A pointer to an array is often technically "equal" to an array itself, but since they have different semantics, there are situations in which they are not interchangeable. Try this one:
int my_array[5] = {5,6,7,8,9};
cout <<my_array[0]<<endl; // output 5
cout <<(&my_array)[0]<<endl; // outputs the address of the first element
cout <<sizeof my_array[0]<<endl; // outputs 4
cout <<sizeof (&my_array)[0]<<endl; // outputs 20