pointer movement what is difference between cs[1], and *cs++ - c

I am trying to understand how the pointers are moving.
Following is the program and I am aware that
if
int cs={1,2,3};
then cs points to cs[0]
what I am not clear is what is *cs pointing to.
#include<stdio.h>
int main()
{
int array[] = { 1, 2, 3, 4, 5 };
int *arrptr1 = array;
int *arrptr = array;
int i;
for (i = 0; i < sizeof(array) / sizeof(int); i++) {
printf("%d, %d, %d\n", array[i], *arrptr1++, *arrptr + i);
}
}
the output of above program is
1, 1, 1
2, 2, 2
3, 3, 3
4, 4, 4
5, 5, 5
then my understanding *arrptr should increase the value stored at
*arrptr
should get incremented by 1.
Where as what I observe is the pointer is moving to next location.So just want to know what is wrong in my understanding?
UPDATE
As per the replies below I understand that
print("%d", *arrptr1++);
in such a statement evaluation of operators is from right to left.
Hence in *arrptr1++ the ++ will get evaluated first and then arrptr and then *
So to confirm the same I wrote another program
#include<stdio.h>
int main()
{
int array[] = { 10, 20, 30, 40, 50 };
int *q1 = array;
printf("q1 = %p\n",q1);
printf("*q1++ = %d\n",*q1++);
printf("q1 = %p\n",q1);
printf("*q1++ = %d\n",*q1);
}
The output of above program is different than the expected operator precedence by above logic.
The output I got is
q1 = 0x7ffffcff02e0
*q1++ = 10
q1 = 0x7ffffcff02e4
*q1++ = 20
So I was expecting in the 2nd line of output instead of *q1++ = 10 following *q1++ = 20
so did the operator precedence not happened right to left?

*arrptr1++ is parsed as *(arrptr1++), not (*arrptr1)++.

Whenever you use dereference operator * and pre-increment(pre-decrement) or post-increment(post-decrement) operator on a variable simultaneously ,the order of operation is from right to left (if parenthesis are not used).
What you want to do is
(*arrptr)++
because of higher precedence of (), it will force the compiler to first access the element pointed to by arrptr and then increment its value.
When you do this *arrptr++ , as I've said it first operates rightmost operator (i.e. ++)
and then the dereference operator.
If you will write
EDITED (only the comment): *++arrptr // increment the pointer then access
it will first advance the pointer and then access the value
stored in the address now pointed to by arrptr.
One more thing,The comma used for separation of function argument is not the comma operator so the order of evaluation of the arguments is undefined. (already been told)

What happens is that *arrptr1++ is interpreted as *(arrptr1++), which means that the pointer to the array is increased by one each time in the loop, and hence it will point to the same element as array[i]. *arrptr + i on the other hand is interpreted as "the value of the array element pointed to by arrptr plus the integer i". In this loop it means it will display the same thing as array[i], but it is not pointing at the same element (arrptr is always pointing to the first element in your array). If you change the values in the array to something more random, it should be obvious when you run the program again.

cs = &cs[0] ( cs is equal to the address of cs sub 0) ; *cs = cs[0] (cs pointer is equal to cs sub 0) ; You should remember that *'s hide the [].
// here is a print function with a pointer
int foo[5] = { 2, 9, 1, 3, 6};
int *walker, count;
walker = foo;
for (count = 0; count < 5; walker++, count++)
printf("Array[%d]: %d\n", count, *walker);
Recap: walker is equal to &foo[0], so when you increment walker (eg. walker++) you're moving the pointer to the next address which is foo[1]. And when we are printing the value we can't say ..., walker); since walker( &foo[whatever] ) is pointing to an address, we need to dereference the pointer to get the value. Again, the most important thing to remember
array = &array[0] AND *array = array[0]

Related

How does *(array + 3) work?

I am studying for my midterm. this was an example code
#include <stdio.h>
void doubleArray(int array[], int length)
{
for (int i = 0; i < length-2; i++) {
array[i] += array[i];
}
length += 5;
printf(“%d\n”, length); // Question 29
}
int main(int argc,char *argv[]) {
int integers[6] = { 3, 4, 5, 6, 7, 8};
int length = 6;
printf(“%d\n”, integers[4]); // Question 28
doubleArray(integers, length);
printf(“%d\n”, *(integers + 3)); // Question 30
printf(“%d\n”, *(integers + 4)); // Question 31
printf(“%d\n”, length); // Question 32
}
for questions 30 and 31
the answer is that it prints 12 (30) and 7 (31)
can someone explain to me why and what that "*(integers + 3)" means?
* is a dereference operator on a pointer.
This means that it will "get" the value that's stored at the pointer address of the item right after it ((integers + 3)).
It will interpret this value as the dereferenced type of the item after it (int since (integers + 3) is of type int*)
(integers + 3)
integers is a pointer to the address of the first element of the integers array.
That means that if integers contained [1, 2, 3, 4, 5] then it would point to where 1 is stored in memory.
integers + 3 takes the address of integers (i.e. where 1 is stored in memory) and adds the amount of address space required to store 3 ints (since the pointer is of type int*). Advancing it by one space would give you the address of 2 in memory, advancing it by two spaces would give you the address of 3 in memory, and advancing it by three spaces gives you the address of 4 in memory.
How this applies to your example
(integers + 3) gives you the address of the 4th item in the integers array since it's the first element's address plus the size of three elements.
Dereferencing that with the * operator, gives you the value of the 4th element, 12 (since the value of 6 was doubled by doubleArray)
The same applies to *(integers + 4) except that doubleArray didn't double the 5th element so it gives you 7.
How doubleArray works
for (int i = 0; i < length-2; i++) means start the variable i at 0 and advance it until it is length - 2.
This means it takes the value of everything from 0 to the value of length - 2 but executes the body of the loop for values from 0 to length - 3 since the < is exclusive (the conditional is evaluated BEFORE executing the body of the loop so when i == length - 2 the condition is false and the loop terminates without further execution.
So, for each element, excluding the last two, the element in array is added to itself.

Using negative number as array index

I came along a competitive question that asks the output of the following:
#include <stdio.h>
int main()
{
int a[] = {0,1,2,3,4};
int i, *ptr;
for(ptr = a+4, i=0; i <=4; i++)
printf("%d", ptr[-i]);
return 0;
}
I did read this topic: Are negative array indexes allowed in C? However it was unclear to me how the -ve symbol generates the array in the reverse order, ie. 4, 3, 2, 1, 0.
First, recall that in C the expression ptr[index] means the same thing as *(ptr+index).
Now let's look at your expression again: ptr is set to a+4 before the loop; then you apply -i index to it. Therefore, the equivalent pointer arithmetic expression would be as follows:
printf("%d", *(a+4-i));
This expression iterates the array backwards, producing the results that you see.
The reason it works is because the [] operator does pointer addition.
When you reference
a[x]
Whats actually happening is its taking the memory address of a and adding the sizeof(int)*x
So if you set ptr to a+4, you are going to a+sizeof(int)*4
then, when you put in a negative value, you move backwards through the memory address.
ptr[-i] decays into *(ptr + (-i)). At the first iteration, when i = 0, ptr[-i] accesses last element of a array, because initially ptr was set to be equal a + 4, which means - take address of beginning of a and add 4 * sizeof(int) (because ptr was of size int). On every next iteration, when i is incremented, previous element of array is accessed.
In is for statement
for(ptr = a+4, i=0; i <=4; i++)
pointer ptr is set to a+4 It could be done also the following way
ptr = &a[4];
If you tray to output the value pointed to by the pointer as for example
printf( "%d\n", *ptr );
you will get 4. That is the pointer points to the last element of the array.
Inside the loop there is used expression ptr[-i] . for i equal to 0 it is equivalent to ptr[0] or simply to *ptr that is the last element of the array will be outputed.
For i equal to 1 expression ptr[-i] is equivalent to a[4 - 1] or simply a[3]. When iequal to 2 when expression ptr[-i] is equivalent to a[4 - i] that is a[4 - 2] that in turn is a[2] and so on.
SO you will get
4321
a+4 gives a pointer to the fifth element of a. So ptr refers to that location.
Then the loop counts i from 0 up to (and including) 4.
The dereference ptr[-i] is equivalent to *(ptr - i) (by definition). So, since i is 0 and ptr is a+4, it's equivalent to a+4-0, then a+4-1, then a+4-2, and so on until a+4-4, which is (obviously enough) equal to a.
As I mentioned in my comment in C/C++
a[b] == *(a+b) == b[a]
For your case all of these is fine
printf("%d", *(a + 4 - i));
printf("%d", a[4 - i]);
printf("%d", 4[a - i]);
...

Pointer incrementation causing segmentation fault

This code causes a segmentation fault when running. It's due to the odd pointer incrementation, but I don't understand why this is a problem, as it seems to make sense.
I think it should: increment the pointer, then dereference the unincremented pointer, then increment the value 10 to 11. So out = 11, and the first value in the array is now 11. So this loop should print out 11, 21, 31, 1, then go on infinitely printing out values outside the array. This is clearly bad practice but we just want to see why this double pointer incrementation isn't valid.
My code:
int main() {
int myarray[4] = {10,20,30,0};
int *p = myarray;
int out = 0;
while (out = ++(*p++)) {
printf("%d ", out);
}
}
The while loop never terminates:
First iteration:
*p = 10, out = 11
Next iteration:
*p = 20, out = 21
Next iteration:
*p = 30, out = 31
Next iteration:
*p = 0, out = 1
Next iteration:
You are accessing unauthorized memory, which leads to undefined behavior.
Update
After the last item from the array is accessed, the part of the stack frame that contains code gets trampled over by the increment operator. Hence, the code cannot be expected to behave in a logical manner.
Here:
while (out = ++(*p++))
The preincrement (the first "++") returns the incremented value. So when you reach the end of the array, it returns 1, which evaluates to true, and the loop keeps going.
When p exceeds the range of myarray, deference causes undefined behavior.

Trying to print form array or array addresses...not getting it?

new here, trying to learn a piece of C with the great help of you guys, this could be a basic questions here....sorry you have start from basic.
void main()
{
char* arr[3] = {"baba","tata","kaka"};
char* arr1[3] = {"baba1","tata1","kaka1"};
char* arr2[3] = {"baba2","tata2","kaka2"};
char** array_all[] = {arr,arr1,arr2};
printf("%s\n",*array_all[0]);
//please guide me how to access individual entity(as arr[1], arr1[2],arr3[1]) //from each array using array_all
}
I'm not sure if this is exactly what you were looking for.. but this is what I understand so far.
You are wanting to access the individual elements of array_all (the elements arr, arr1 and arr2)? If so then all you do is...
array_all[0][i];
Where i is the element that you want to access.
The reason for this is because the index operators ([ and ]) actually dereferences a pointer and offsets the pointer (as in adds it by some integer, i.e. you move down in memory) that you specify. I recommend reading up on pointer arithmetic if you have no clue what happens if you add a pointer by some integer.
For example:
int x[] = { 1, 2, 3 };
// writing x[i] is the same as *(x + i)
int i = 2; // the element you wish to access
*(x + i) = 4; // set the ith (3rd) element to 4
*(x + 1) = 43; // set the 2nd element to 43
// Therefore...
// x now stores these elements:
// 1, 43, 4
// proof: print out all the elements in the array
for(int i = 0; i < 3; ++i)
{
printf("x[%i]=%i\n", i, x[i]);
}
Also, writing x[0] is the same as writing *x, since the array name actually points to the first element of the array.
OH and one thing, main should actually return an integer result. This is mainly used for error checking in your program, 0 usually means no error occurred and every other error-code (number other than 0) is some specific error related to your program, that you can choose.
i.e.
int main()
{
// e.g. for an error code
/*
if(someErrorOccured)
{
return SOME_ERROR_OCCURED_RETURN_VALUE;
}
*/
return 0; // this is at the end of the function, 0 means no error occured
}
change your printf statement line with this..
printf("%s\n",array_all[i][j]);
In place of i keep your array number and in place of k give your required element number. It works.

C: Pointer confusion

I understand this is part of the basic stuff, but i am stuck :-(
Can someone please help me?
Program 1:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a=1,b=2,c;
c=(a+b)++;
}
Why is the output an error? lvalue required?
Program 2:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *p1="name";
char *p2;
p2=(char*)malloc(20);
memset(p2,0,20);
while(*p2++=*p1++);
printf("%s\n",p2);
}
Why is the output, an empty string? And if i reverse the order of increment, that is: while(++*p2=++*p1);, why the lvalue error comes?
For the first question,(a+b)++ means "increment the value of a+b by 1".
You cannot increment a+b, though, for it's not a variable. What would you expect to happen in the following code?
int a = 1, b = 2;
printf("a = %d, b = %d, a+b = %d\n", a, b, a+b);
(a+b)++;
printf("a = %d, b = %d, a+b = %d\n", a, b, a+b);
Clearly the first printf should print
a = 1, b = 2, a+b = 3
But what about the second one?
a = ?, b = ?, a+b = 4
It's not clear what a or b should be if we increment the sum.
As for the second question, remember that you're changing p2 when you copy over the data, so when you ask to print out what it's pointing at, it's pointing at the end of the string, not the beginning.
An easier way to do the string copy would be to use strcpy, like so:
strcpy(p2, p1);
Note, this is only safe because you know that the size of the string in p1 isn't greater than the size of p2. If you're not sure about the size of the string (for instance, if you get the string from user input), you'll need to be careful, as is outlined on Wikipedia.
As for why while(++*p2=++*p1); doesn't work, while while(*p2++=*p1++); does:
Postfix-++ has higher precedence than *. This means, *p2++ means *(p2++).
So
*(p2++) = something;
is the same as
*p2 = something;
p2 += 1;
Meanwhile, ++*p2 means ++(*p2), or "whatever p2 points to, incremented by one".
Again, you get the problem, if you say:
int a = 5, *p2 = &a;
++*p2 = 10;
printf("a = %d\n", a);
What would you expect this to print? If anything, it should print 9, because you're telling the compiler that *p2+1 = 10.
You can't expect a C-compiler to solve that equation, however, so in order to keep the language simple and efficient, this sort of thing is forbidden.
c=(a+b)++;
a+b is not a lvalue - how would you want to assign something to the result of an addition (a rvalue) - and the ++/-- operators do assign the new value.
while(*p2++=*p1++);
You p2 points at the \0 at the end of the string. You need to store the original address p2 points to before your loop:
char *p3 = p2;
while(*p2++=*p1++)
;
printf("%s\n",p3);
c=(a+b)++;
The ++operator doesn't work with temporary variables. (a+b) forms a temporary.
while(*p2++=*p1++);
You're incrementing p2 here. After the loop, p2 no longer points to the beginning of the memory block returned by last malloc() call.
If you look at the while loop:
while(*p2++ = *p1++);
remember that an expression is "True" in C if it is non-zero, and false if it is zero. Even though the loop has no body, the flow of control is still:
check condition -> execute statement in body --> check condition
and here, "check condition" means "evaluate the statement and see if it is non-zero".
The while loop continues to operate until p1 points to zero, at which point control passes to printf.
e.g.
int main()
{
int array1[] = {2, 3, 1, 0, 3, 5};
int array2[20];
int * p2 = (int *)memset(array2, 0, 20*sizeof(int));
int * p1 = array1;
while(*p2++ = *p1++) {
printf("In while: p1 is %d\n", *p1);
}
printf("Out of while: %d\n",*p2);
return 0;
}
yields:
In while: p1 is 3
In while: p1 is 1
In while: p1 is 0
Out of while: 0

Resources