Pointers problem - c++

I have a question.
I created a correctly initialized integer pointer
int * p
and a correctly initialized integer array
int * array1 = new int[]
Which of the following is legal code?
p = array1;
array1 = p;
Or are both correct?
is this possible as well
p[0] since, to my pointer arithmetic knowledge, it doesn't add anything.
All in c++

If the question is trying to get at pointers versus arrays, they are not always compatible. This is hidden in the presented code because the array is immediately converted to a pointer.
int* array1 = new int[5]; // Legal, initialising pointer with heap allocated array
int array2[5] = {0}; // Declaring array directly on the stack and initalising with zeros
int *p = 0; // Declaring pointer and initialising to numm
p = array2; // Legal, assigning array to pointer
p = array1; // Legal, assigning pointer to pointer
array1 = p; // Legal, assigning pointer to pointer
array2 = p; // ILLEGAL, assigning pointer to array
Here array2 has an array type and cannot be used to store a pointer. Actually, the array cannot be reassigned at all, as it is not an l-value.
int array3[5] = {0}; // Declaring array directly on the stack and initalising with zeroes
array3 = array2; // ILLEGAL, array not an l-value
The array has a fixed address and reassiging it would be similar to trying to write:
int i = 0;
&i = p;
[Hopefully, trying to reassign the location of a variable is obvious nonsense.]

Both are legal.
The first, "p = array1", will cause your correctly initialized integer pointer to be leaked and to point p to the first occurrence of the array that array1 points to.
The second, "array1 = p", will cause the correctly initialized integer array to to be leaked and to point array1 to the single int that p points to.
So I suspect I'm missing something. Could you perhaps post complete code?

If both p and array1 are declared as "int *", as you imply here, then either assignment is legal, by definition.

both are leagal.
passing adresses to eachother. dont knw what u want to do

According to the explanation provided in this site. The first assigned in is correct but the second assignment cannot be considered valid. Please look under the title 'Pointers and arrays'.

You can assign your array variable to pointer variable. So p = array1 is correct.
You can refer this code.
#include <iostream>
using namespace std;
int main ()
{
int numbers[5];
int * p;
p = numbers; *p = 10;
p++; *p = 20;
p = &numbers[2]; *p = 30;
p = numbers + 3; *p = 40;
p = numbers; *(p+4) = 50;
for (int n=0; n<5; n++)
cout << numbers[n] << ", ";
for (int n=0; n<5; n++)
cout << p[n] << ", ";
return 0;
}
If both are pointers then no need to declare pointer as array like int *array1 = new int[].

Both variables are of type pointer to int. So both assignments are legal. The fact that one of the variables is an array doesn't matter in C. Arrays and pointers are the same after initialization.

"I created a correctly initialized integer pointer int * p and a correctly initialized integer array int * array1 = new int[]"
First of all, keeping the syntactical mistakes aside, the terminology is wrong.
int *p; - Here you are just declaring a pointer to hold an integer variable's address. You are not initializing it. Declaration is different from initialization and initialization is different from assignment.
int *array1 = new int[]; - Keeping the error aside, this is not an initialized integer array. array1 is a pointer pointing to an array of integers.
And passing nothing to [] is incorrect. A value needs to be passed that decides number of memory locations to be allocated for holding integer values.
Answering the questions.
Which of the following is legal code?
p = array1;
If, array1 is properly initialized it's correct. p points to the first integer in the array1. Even if it is not properly initialized also, it is correct. In this case, both array and p points to garbage values.
int* array1 = new int[5]; // Notice **5** being passed.
array1 = p;
Infact this operation is useless. Both p and array1 were both pointing to the same location earlier. But this is legally correct.
is this possible as well p[0] ?
Yes, it's correct. p can dereference to 0 to 4 as it's index values. If you just want to p[0], in that case -
int* array1 = new int ; // Notice nothing being passed.

Related

Allocating memory to pointer multidimensional array with new

I can't understand some basic thing in c++ and have been wondering. Please help me.
I understand that p points to memory that would be a 2D int matrix of 3x4 size.
int(*p)[3][4];
1) Why can't I allocate memory like following?
p = new int[3][4];
2) It should be like following to work. But why?
p = new int [1][3][4]; //or new int [5][3][4]; etc
3) What does following line of code mean? It is semantically correct but what is it doing? What is significance of empty [] in following line?
p = new int [ ][3][4];
c++ is a strongly typed language. int is not the same as int*. Likewise int[3] is not the same type as int*. But just lightly poke int[3] with a stick and it will fall apart and decay to an int*. c++ does this because c does it.
Why can't I allocate memory like following?
p = new int[3][4];
Because the new is returning a pointer to int[4]:
auto p1 = new int[3][4]; // int(*p1)[4]
The array has decayed to a pointer. It has lost the type and first dimension. It would be best to avoid pointers for arrays and stick to using templates and references. Or better yet, prefer std::vector or std::array.
You could have multiple pointers to the same address, but with different types, which can be confusing.
2) It should be like following to work. But why?
p = new int [1][3][4];
In this example the array of int[3][4]s has also decayed to a pointer:
auto p2 = new int [1][3][4]; // int(*p2)[3][4]
So here the value returned by new can be assigned to p because it has the same type. Note however that the pointer type doesn't include information about the size of the array, it only has a type that points to elements which happen to be arrays of a lower dimension (that haven't decayed to pointers).
3) What does following line of code mean? It is semantically correct
but what is it doing? What is significance of empty [] in following
line?
p = new int [ ][3][4];
This might not always compile, and if it does then it is a compiler extension that will determine the value of the empty square brackets.
Because in C, "int *p" has two interpretations.
You can consider P to be a pointer to a single integer, but it can also be considered to be a pointer to an array of integer.
A common example, strings.
char *a = "hello";
"a" is a pointer to a single character, 'h', but more commonly it is treated as a pointer to an array of characters, aka a string.
So, you can do this:
char * a = new char[6];
strcpy(a, "hello");
I believe that your third example is not valid C++.
While this:
p = new int [9][3][4];
Allocates an array of 9 two dimensional arrays of 3x4.
Try this test:
int test()
{
int(* p)[3][4] = new int[1][3][4];
printf("sizeof(p)=%d, sizeof(*p)=%d\n", sizeof(p), sizeof(*p) / sizeof(int));
size_t q1 = (size_t)&p[0][0][0];
size_t q2 = (size_t)&p[1][0][0];
printf("p, diff: %d\n", (q2 - q1) / sizeof(int));
size_t r1 = (size_t)&p[0][0][0];
size_t r2 = (size_t)&p[0][1][0];
printf("p, diff: %d\n", (r2 - r1) / sizeof(int));
size_t s1 = (size_t)&p[0][0][0];
size_t s2 = (size_t)&p[0][0][1];
printf("p, diff: %d\n", (s2 - s1) / sizeof(int));
return 0;
}

Why in C++, I don't need to dereference a pointer to an array in order to access items in the array

I'm currently learning pointer. And when I create a pointer to an array with int type, I found that I can directly index the pointer without deferencing the pointer and the compiler still output exact items in my array. I do not understand why this works and why we don't need to first deference the pointer.
Code that without dereference
int arraySize = 5;
int* theArray = new int[arraySize];
for(int i = 0; i < 5; i++)
{
theArray[i] = i;
}
for (int i = 0; I < 5; i++)
{
std::cout << theArray[i] << std::endl;
}
And this gives me the output
Output without derefercing
However, when I wrote like this:
for (int i = 0; i < 5; i++)
{
(*theArray)[i] = i;
}
My compiler says that: Error: expression must have pointer-to-object type. (I'm using Visual Studio 2013.)
Any help would be appreciated.
Code that without dereference
[ code ]
That's incorrect. You are most certainly dereferencing your pointer:
theArray[i] = i;
That's a pointer dereference. The [] operator dereferences the pointer. This is equivalent to:
*(theArray+i) = i;
As you know, adding or subtracting a value to a pointer advances or decrements the pointer, producing a new pointer value, and then the pointer gets dereferenced.
Also:
*p = q;
is equivalent to
p[0] = q;
The [] operator is just a shorthand for adding an offset to a pointer, and dereferencing the resulting pointer with the * operator. The end result is exactly the same.
I do not understand why this works and why we don't need to first deference the pointer.
The first version is correct:
for(int i = 0; i < 5; i++)
{
theArray[i] = i;
}
because theArray[i] is actually *(theArray + i) - essentially pointer arithmetic is equivalent to array index.
On the other hand, the 2nd version is incorrect:
for (int i = 0; i < 5; i++)
{
(*theArray)[i] = i;
}
That's because (*theArray)[i] is actually pointer to array (not the array itself), and so it caused a type mismatch as the compiler already suggested.
A few other answers correctly say that *(theArray + i) is equivalent to theArray[i]. But the point I think you missed when learning is that unlike most objects a pointer to an array is not a pointer to the array that is then dereferenced, and then array logic, it is only a pointer to the first element of the array. That's why this:
int *myIntPointer = new int[5];
is NEARLY the same as this:
int myIntArray[5]; // "True" array on the stack
But you can also point it at something else:
int myInt = 10;
delete [] myIntPointer;
myIntPointer = &myInt;
It's also why doing the follow CAN give a compiler warning, but can also work (depends on the compiler):
myIntPointer = myIntArray; // Sometimes works, sometimes doesn't, compiler dependent
That's because allocating an array with new int[size] returns a pointer to an int not a pointer to an "array" type.
It's a weird corner case of C/C++ that arrays and pointers interact this way. You also run into it if you try and pass one of the "true" arrays into a function.
theArray[i] literally corresponds to *(theArray + i) so it already dereferences the pointer.
Indeed when you try to call operator[] on *theArray it yields you an error because it expects a pointer, not a real object.
You're actually asking the wrong question for your misunderstanding — you should be asking why you can write
int* theArray = new int[arraySize];
In c++, array types are not like other types, and have a number of special cases and rules that make them behave differently from other types. In particular, new T[N] does not return a "pointer to an N-long array of T", it returns a "pointer to T". (specifically, to the first element of the newly created array)
For a more mindboggling example of this, observe:
typedef int T[5];
T* p = new T; // this does not compile
int* q = new T; // this does compile

array pointers in c++

How do you access/dereference with arrays in c++??
for example, if I have this code
int num[] = {0,1,2,3};
int *p = &num;
I thought p was point to the first element in num array?
For some reason, I get a compiler error.
I want to use pointers and increments to access and change the value that is pointing,
for example, p gets the address of the first variable in the int array num and if I increment p, I get the address of the second variable in the int array num.
Any tips would be appreciate it.
I thought p was point to the first element in num array?
No. int *p = &num; is wrong, since &num is not a pointer to an int, i.e. int*, but is actually a pointer to an array of ints, i.e. int (*) [4].
To get a pointer to the first element, you can use int *p = num;, or int *p = &num[0]; instead.

C++ what exactly does new <datatype>(<value>) do?

In this code:
int * p = new int(44);
p is allocated on the heap and the value it points to is 44;
but now I can also do something like this:
p[1] = 33;
without getting an error. I always thought
int * p = new int(44);
was just another way of saying "P is allocated on the heap and points to an address containing 44" but apparently it makes p a pointer to an array of ints? is the size of this new array 44? Or is this result unusual.
You were right: P is allocated on the heap and points to an address containing 44. There's no array allocated. p[1] = 33; is what they call "undefined behavior". Your program might crash, but it's not guaranteed to crash every single time you do this.
int *p_scalar = new int(5); //allocates an integer, set to 5.
If you access p_scalar[n] (n <> 0) it may crash
In your example, the C++ language gives you a default implementation for the subscript operator for pointers that looks somehow similar to this:
(*Ptr)& operator[](size_t index)
{
return *(address + index*sizeof(*Ptr));
}
This can always be overloaded and replaced for any type. Integers are not an exception, when you say:
int * pointer = alocate_int_array();
pointer[1] = 1;
You're using the compiler-augmented default implementation of that operator.

Updating map values in c++

Newb question here:
how can I have the value stored in Maptest[2] update along with the variable?
I thought you could do it with pointers, but this doesn't work:
map<int, int*> MapTest; //create a map
int x = 7;
//this part gives an error:
//"Indirection requires pointer operand ("int" invalid)"
MapTest[2] = *x;
cout << MapTest[2]<<endl; //should print out 7...
x = 10;
cout <<MapTest[2]<<endl; //should print out 10...
What am I doing wrong?
You need the address of x. Your current code is attempting to dereference an integer.
MapTest[2] = &x;
You then need to dereference what MapTest[2] returns.
cout << *MapTest[2]<<endl;
Try this instead:
MapTest[2] = &x;
You want the address of x to store in the int*. Not the dereference of x, which would be what ever is at the memory location 0x7, which is not going to be valid.
There are at least 2 problems here:
int x = 7;
*x; // dereferences a pointer and x is not a pointer.
m[2] = x; // tries to assign an int value to a pointer-to-int value
// right
m[2] = &x; // & returns the address of a value
Now you have a new problem. x has automatic lifetime, it will be
destroyed at the end of its surrounding scope. You need to allocate it
from the free store (a.k.a. the heap).
int* x = new int(7);
m[2] = x; // works assigns pointer-to-int value to a pointer-to-int value
Now you have to remember to delete every element in the map before
it goes out of scope or you will leak memory.
It is smarter to store values in a map, or if you really need to
store pointers to store a suitable smart pointer (shared_ptr or
unique_ptr).
For the printing:
m[2]; // returns pointer value
*m[2]; // dereferences said pointer value and gives you the value that is being pointed to