Pointer Increment Decrement Syntax Difference - c++

when I work on pointers on a website I stick at a point.
When I write the given example I can assign adresses of array on a pointer for an increment a pointer example like ptr = arr; and it works correctly, but when I do the same thing for the decrement example it doesn't work it works only when I write like this ptr = &arr[2]. Why I have to write ampersand for decrement example? what is the difference between those two?
int main()
{
int arr[3]={10,20,30};
int *ptr,i;
ptr=arr;
for(i=0;i<3;i++)
{
printf("adress of variable arr[%d] %x\n",i+1,ptr);
printf("value of arr[%d] = %d\n",i+1,*ptr);
ptr++;
}
return 0;
}

You don't have to write it, just use the pointer:
ptr = var + 2 ;
for(i=0;i<3;i++)
{
printf("%d" , *ptr ) ;
ptr-- ;
Note that the last element is at +2 not +3.

in case of an int arr[3], &arr[0] and arr points to the same thing, the base address of the array, or, the address of the first element in the array. That's why in your increment case, you're allowed to write ptr = var which is nothing but storing the starting address in a separate pointer.
In case of decrements, there is nothing which can point directly to the end-of-array element address. So , you have to use the address-of-last-element [&arr[n-1], n being the size] to denote the address of the last element.

The difference is that in "decrement" case you use []. Think of arr as reference to whole array thus it is ok (compiler wise) to do ptr=arr or ptr=&arr with same result. On the other hand arr[3] is a reference to object in array, so you need to get its address explicitly (no compiler optimization for you).

Related

What does this mean *((int*)(&val) +1)

I'm trying to understand this line of code. Can someone help me? Is it saving the result in the variable val or in the address of the variable val?
*((int*)(&val) +1)= A*(y) + (B - C)
Thank you
&val take the address of val
(int*)(&val) consider this address as a pointer to int
(int*)(&val) +1 increment this address by 1 (times sizeof(int))
*((int*)(&val) +1) = ... assign the right hand side value at this incremented address
It is interpreting val as if it was an array of integers, and storing the result of the right hand expression in its second element. To understand exactly the point of it all you should provide some more context (my guess: is it manipulating the raw content of double values?)
Notice that, depending on the type of val, this may be undefined behavior due to strict aliasing rules.
Divide expression *((int*)(&val) +1) into smaller ones to understand it:
take address of val (&val) and treat it as a pointer to an int (int *)
add 1 +1 to this pointer which means 'move pointer to next int' as it was an array of ints.
finaly by combining * and = apply right hand side expression to int pointed by pointer.
I hope others have answered your question. Adding to what others have said, the same code can be written as follows:
(int*)(&val)[1]= A*(y) + (B - C)
where (int*) will type cast &val as an implicit pointer to an integer which points to the address of val and [1] indicates the first integer location ahead of the location where val is stored.
This is how arrays are interpreted. Say you have an array
int a[10];
For this array, 'a' is a pointer which points to the base address ( address of the element a[0] ), and a[i] is nothing but *(a+i), i.e. the element which is i locations ahead of the first element of the array.
This is not correct code and you should never use it
Imagine this class:
class A {
int number = 10;
public:
void print(){ std::cout << number; }
};
The int number is private for the access not the use!
So how can we access this private int.
Simply:
A obj;
*( (int*) ( &obj ) ) = 100;
obj.print();
output
100
demo
Now if you would have more than one data then how to access?
by this syntax:
*((int*)(&val) +1)
It says:
find the address of the first data,
one index go ahead,
cast it to the int*,
then dereference it,
then initialize it

Why it doesn't yield memory-addresses when looping through a pointer?

When we print ptr, it gives a memory address, but when we loop through it, we get array elements. What's causing the difference & why so?
int main()
{
string texts[] = { "one", "two", "three" };
string* ptr = texts;
for (int i = 0; i < 3; i++) {
cout << ptr[i];
}
_getch();
return 0;
}
When we print ptr, it gives a memory address, but when we loop through it, we get array elements.
ptr is a pointer so when you print it you get a memory address.
Note ptr[i] is the same as *(ptr + i). So when you loop using array syntax ptr[i] you are dereferencing it and so you get the data itself.
The type of ptr is string* - a pointer to a string. The type of ptr[i] is string.
cout is a global instance of class ostream. This class defines an insertion operator, i.e. operator<<() for string objects which specifically prints the contents of the string. Therefore cout << ptr[i] prints the text. On the other hand, ostream does not specifically define an insertion operator for pointers to strings. So the closest matching definition is operator<<(void*) - an insertion operator for pointers in general. This just prints the address.
ptr[i] is the same as *(ptr + i).
a container object like a string or an array is a pointer to the first element in that container. the [] operator access a certain object based on the starting location like #artm said. this question is the result of a lack of understanding how variable memory allocation works. look into that for a more complete answer.
When you write string* ptr= texts; the starting address of the array is stored in the pointer memory i.e. the pointer now points to the starting address of the array. So, whenever you'll print ptr, an address will be printed.
But when you loop through it i.e. ptr[I] it's evaluated as *(ptr+i). * is the dereferencing operator which means it gives the value stored at the address given to it. Therefore, *(ptr+i) becomes the_value_at(location saved in ptr + i more units). Which is why you get array values.

Understand how this double becomes an array?

So I'm currently reading and learning a code from the internet (related to artificial neural network) and I found a part of the code that I don't understand why it works.
double* inputNeurons;
double* hiddenNeurons;
double* outputNeurons;
This is how it was declared. Then in this next code, it was changed and used as an array?
inputNeurons = new( double[in + 1] );
for ( int i=0; i < in; i++ ) inputNeurons[i] = 0;
inputNeurons[in] = -1; // 'in' is declared in the function as an int
So, I want to understand why and how it works. Did it become an array of "doubles"? If so, in what way can I also use this? Can this be used for struct or even class?
Every array can be treated as a pointer. But that does not mean every pointer is an array. Do not mix this up!
Assuming we have an array int test[..], the variable name also represents the address where the array is stored in the memory. So you could write
int * p = test;
At that moment my pointer p "becomes" an array, where "becomes" means 'points to an array'. Your example is similar - the only difference is that the memory is allocated dynamically (heap) and not on the stack (as in my example).
So how are the elements accessed?
Let's say, we want to get the first element (index 0).
We could say
int i = test[0];
or we could say
int i = *p;
Now we want to get the element at index 1:
int i = test[1];
Or - by using pointer arithmetics we could write
int i = *(p + 1);
In C++ (and C) pointers support indexing operator [] which basically adjusts the value of the pointer by the amount specified times the size of the type pointed.
So basically
inputNeurons[5] = 0;
is equivalent to
*(inputNeurons+5) = 0
Now this doesn't give you any guarantee about the fact that inputNeurons points to an address which is correctly allocated to store at least 6 double values but syntactically it is correct and well defined.
You are just adjusting an address to point to the i-th element of a given type starting from the specified address.
This means that
double x;
double* px = &x;
px[5] = 0;
Is syntactically correct although it is wrong, since px+5 is an address which points to memory which has not been reserved correctly to hold that value.
The pointer of type double (double* inputNeurons;) just gets assigned to point to the beginning of an dynamically allocated array (new( double[in + 1])) of the same type. It does not become an array.
You can do this with any other pointer and regular array of the same type. As a matter of fact an array is a pointer to specific address (to its beginning, i.e. to the element with index: 0).
When you increment the pointer by + 1, that one means 1 * type_size (i.e 1 * size_of_double)
In your case: inputNeurons points to the address of the first element of the array. If you dereference it: *inputNeurons, you will get the value stored at that address (if inputNeurons was an array, it would be equivalent to: inputNeurons[0] ). To access the next element just increment by one (*inputNeurons + 1).

Pointer to array dilemma

I have a rather simple question about arrays and pointer to arrays.
consider this code fragment..
int (*ptr)[3]; //A pointer to an array of 3 ints
int arr1[3] = {2,4,6,};
ptr = &arr1; //ptr now points to arr1
//3 different ways to express the same address
cout << &arr1 << "\t" << arr1 << "\t" << &arr1[0] << endl;
Now if:
&arr1 == arr1 == &arr1[0]..
why is this code not correct:
ptr = arr1;
or
ptr = &arr1[0];
This has been driving me crazy...so please any explanation would be appreciated. Also please not that this is not an homework question, just something I'm trying to get a grips on.
In
ptr = arr1;
arr1 is converted to an int*, so you're trying to assign from an incompatible pointer type. &arr1[0] is directly an int*, without conversion, so again incompatible.
&arr1 == arr1 == &arr1[0]
is wrong, since the entities have different types. They only point to the same address, so when printing out, they give the same result.
In most contexts, an expression with an array type is implicitly converted to a pointer to the first element of such array, as explained by 6.3.2.1p3:
Except when it is the operand of the sizeof operator, the _Alignof operator, or the
unary & operator, or is a string literal used to initialize an array, an expression that has
type array of type is converted to an expression with type pointer to type that points
to the initial element of the array object and is not an lvalue.
Thus the right-hand side of your assignment
ptr = arr1;
is implicitly converted to an incompatible pointer type (int* vs. int (*)[3]), and can't be stored to the pointer variable without a cast.
This isn't really an exception to any rule, as you need to use the unary & operator with other types, too:
T val, *ptr;
ptr = &val;
Below programme will help you to better understand difference between
pointer_to_first_member_of_array, pointer_to_1D_array, pointer_to_2D_array.
Please carefully look at the programme, execute it and see output.
#include<stdio.h>
int priv_element = 88;
int array[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int next_element = 99;
main (int argc, char *argv[])
{
int *ptr_to_first_element = &array[0][0];
int (*ptr_to_1d_arry)[5] = &array[0];
int (*ptr_to_2d_arry)[2][5] = &array;
printf ("Print first num of first array of 2-Dim array: %d\n",
*ptr_to_first_element);
ptr_to_first_element += 5;
printf ("Print first num of second array of 2-Dim array: %d\n",
*ptr_to_first_element);
printf ("Print first num of first array of 2-Dim array: %d\n",
(*ptr_to_1d_arry)[0]);
ptr_to_1d_arry++;
printf ("Print first num of second array of 2-Dim array: %d\n",
(*ptr_to_1d_arry)[0]);
printf ("Print first num of first array of 2-Dim array: %d\n",
(*ptr_to_2d_arry)[0][0]);
ptr_to_2d_arry++;
printf
("Now you increased to point end of 2d-array space. So next to it is next_element on data-seg: %d\n",
(*ptr_to_2d_arry)[0][0]);
}
When you printed the various expressions, it showed you that their values were the same. However, they do not have the same types.
C and C++ include type features to reduce human mistakes and to make it easier to write complicated code. Suppose you had an address in some pointer p and C/C++ allowed you to do either:
float *f = p;
or:
int *i = p;
This would be a mistake, because, generally, whatever bits are in the memory at p do not represent both a useful int and a useful float. By enforcing rules about types, the language prevents a programmer from making a mistake here; the pointer p can only be assigned to another pointer of a compatible type, unless the programmer explicitly overrides the rules with a cast.
Similarly, your ptr is a pointer to an array of three int. At first, it might seem like your arr1 is also an array of three int, so you should be able to assign ptr = arr1;. This is wrong because ptr is merely a pointer, but arr1 is an entire array object. You cannot put an entire array into a pointer; you need to put a pointer to the array into the pointer. To get a pointer to the array, you use the & operator: ptr = &arr1;.
Another thing that is confusing here is that C/C++ includes an automatic shortcut: It converts an array to a pointer to the first element of the array. When arr1 appears in most contexts, it is changed automatically to &arr1[0]. There is not a huge philosophical reason for this; it is just a convenience for the ways we often use arrays. So ptr = arr1; would be equivalent to ptr = &arr1[0];, which is also not allowed. In this form, you can see that arr1 has become a pointer to an int, so you cannot assign it to a pointer to an array of int. Even though the pointer has the value you want, it is the wrong type.
When an array appears as the operand of & or sizeof or _Alignof, this automatic conversion does not occur. So &arr1 results in the address of the array.
A string literal that is used in an initialization such as char a[] = "abc"; is treated specially and is not automatically converted as described above.

Confused: Pointers to Dynamic Arrays Syntax

int* p_bob = new int;
*p_bob = 78;
The above code makes sense to me. I use the de-reference operation to allocation new memory and assign a value of 78.
int* p_dynint = new int[10];
*p_dynint[2] = 12;
This however doesn't make sense. If I try to use the de-reference operator on p_dynint[] I get an error. Why would an array be any different?
*p_bob = 78; this assigns the value 78 to the memory pointed to by p_bob (which represents an int).
p_dynint[2] = 12; simply accesses the 3rd element.
p_dynint[2] is actually equivalent to *(p_dynint+2).
p_dynint[2] is equivalent to *(p_dynint + 2). The derefencing is implied in the [] operator.
It is no real problem to do this:
int* p_dynint=new int[10];
//write first element
*p_dynint=10;
//write second element
*(p_dynint+1)=20;
//write three elements to std::cout
std::cout<<p_dynint[0]<<p_dynint[1]<<p_dynint[10]<<std::endl;
This example also highlights a problem with arrays. You can read and write anything. The output generated by p_dynint[10] is an int but its value is just the next few bytes converted to an int.
Use containers if possible (for further reasoning read this)