postincrement pointers with arrays - c

Cannot understand why value of a[1] is not equal to 10
void main()
{
int a[]={2,1};
int *ptr=a;
*ptr++=10; //trying to update a[1]=10
printf("%d",*ptr);
}
Could someone pls explain this?

Let's take your code, and space it out some:
int main() {
int a[]={2,1};
int *ptr=a;
// Validation
assert(ptr == &a[0]);
// Let's now do what *ptr++ = 10 actually does:
*ptr = 10;
ptr = ptr + 1;
// Validation
assert(ptr == &a[1]);
// Printing. Note that we are printing a[1], not a[0].
printf("%d",*ptr);
}
It might also be helpful to read a quote from cppreference. They are discussing the difference between a postfix increment (ptr++) and a prefix increment (++ptr).
The returned result of the postfix version of the operator is the original operand, with a side-effect being that the operand is incremented/decremented after this result is returned.
The returned result of the prefix version of the operator is the incremented/decremented operand.
It sounds like you want to use a prefix increment, not a postfix increment.

Since ++ has higher precedence than unary *, *p++ is going to be grouped as *(p++) which means: Dereference the old ptr and increment ptr by 1 (as long as the original value is used, the increment can happen at any time). *ptr++=10; will update a[0] to 10.

Your code commented as execution flows:
int main(void)
{
int a[]={2,1}; //sets a[0]=2, a[1]=1
int *ptr=a; //sets *ptr == address of a, or a[0]
*ptr++=10; //sets a[0] = 10 (a[1] unchanged)
printf("%d",*ptr);
getchar();
}
*ptr++=10; assigns the value 10 to the address of a[0], then increments *ptr after that assignment is made.

Related

Why does the compiler return a useless value after I dereference it and perform some operation on it?

j is a pointer which points to i. The first print statement returns the value of i, but when I try to deference the pointer and increment i by 1, it returns a useless value which I suppose is the address of i. Why does this happen, and where can I read about pointers in more detail?
#include <stdio.h>
int main( )
{
int i = 3, *j;
j = &i ;
printf ( "\nValue of i = %u", *j ) ;
*j++;
printf ( "\nValue of i = %u", *j ) ;
}
After *j++ I expect j to point to i and the value of i should now be 4. So when I print *j it should return 4.
I think it should print 4
By that I assume you think you are incrementing i. But in fact you are incrementing the j pointer not the content that it is pointing to. This is because the C operator precedence says that ++ has higher precedence than *.
That is, *j++ is doing:
j++
*j
The second step is a no-op as the result is not used.
What you actually want is: (*j)++

Pointer or address?

// Capitalizes a copy of a string while checking for errors
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
// Get a string
char *s = get_string("s: "); //this is in the cs50.h
char *t = malloc((strlen(s) + 1) * sizeof(char));
// Copy string into memory
for (int i = 0, n = strlen(s); i <= n; i++)
t[i] = s[i];
return 0;
}
The above code is from cs50 2018 lecture #3 . t[i] = s[i] part confused me. As I know, when we say char *t , t will store the address of the first part of the memory that was allocated. So doesn't t[i] give us the address of the memory at t[i] location ? If it is like so, shouldn't we write
*t[i] = s[i] to change the value of t[i] ?
No, the [] array index operator dereferences the pointer and evaluates to the value itself, not its address. The expression s[i] is equivalent to the expression *(s + i). If you wanted the address of the element at index i, you would need to use the & operator, as in &s[i] (which is equivalent to s + i).
int array[] = { 10, 20, 30, 40 }; // create an array for illustration
int *ptr = array; // array type decays to a pointer
// these print the same thing: the address of the array element at index 2
printf("%p\n", ptr + 2); // pointer arithmetic
printf("%p\n", &ptr[2]); // array index operator followed by address-of operator
// these print the same thing: the element at index 2 (= 30)
printf("%d\n", *(ptr + 2)); // pointer arithmetic followed by dereference operator
printf("%d\n", ptr[2]); // array index operator
t[i] actually gives you the ith element of the array. It works the same as s[i], which has the same type.
The syntax t[i] is exactly the same as *(t + i). In other words, pointer arithmetic is performed to get a pointer to the desired element, then the result is dereferenced to get the actual element.
char *s = ...;
char *t = ...;
...
t[i] = s[i];
t[i] is an lvalue, an expression that refers to an object. Oversimplifying a bit [*], if it appears on the left side of an assignment (as it does here), it refers to a particular char object, and the assignment updates the value of that object. s[i] is similar, but it appears on the right side of the assignment, so it yields the value of the object.
It's essentially the same thing as:
int x;
int y;
y = x;
x and y are both names of objects, and they're both lvalues. The y on the left hand side refers to the object. The x on the right hand side yields the value stored in the object.
[*] The oversimplification is that there are contexts other than the left hand side of an assignment in which an lvalue refers to an object rather than yielding its value.
There's a bit more going on here in the way the [] operator is defined (see the comp.lang.c FAQ) section 6 for the relationship between arrays and pointers), but in this case all you really need to know is that s[i] and t[i] are the names of objects.
The gory details are in the C standard, N1570 draft, section 6.3.2.1.

Unexpected behaviour found while dealing with a pointer to an array

Look at the code given below:
#include<stdio.h>
int main()
{
int (*p)[3];
int a[3]={10,11,12};
p=&a;
printf("%d\n", *p[0]);
printf("%d\n", *p[1]);
printf("%d\n", *p[2]);
return 0;
}
printf("%d\n", *p[0]); prints 10 which is expected.
But printf("%d\n", *p[1]); doesn't print 11.
And
printf("%d\n", *p[2]); doesn't print 12.
Why? What's the reason behind this?
Operator precedence. [] has higher precedence than *, so when you write *p[0] it is the same as (*(*(p + 0))) - you do pointer arithmetic on an array pointer.
Meaning that for example p[1] gives you the address of p + 3*sizeof(int) bytes, which is accessing the array out of bounds.
Correct code should be:
printf("%d\n", (*p)[0]);
printf("%d\n", (*p)[1]);
printf("%d\n", (*p)[2]);
*p[k] is *(p[k]), not (*p)[k].
That you get the expected result for *p[0] can be explained by its being the same as p[0][0], and it doesn't matter which order you put the zeros in.
p[1][0] (*p[1]), however, is not the same as p[0][1] ((*p)[1]).
(It's even undefined, since p[1] does not exist.)
int (*p)[3]; is an array of pointers to int.
int a[3]={10,11,12}; is an array of int. Arrays and pointers share a lot of properties. You can use array notation for pointers for example.
Lets take a normal pointer int *p = a which is the same as int *p = &a[0]. Now the pointer points to the first element of the array. And you can use it the same way as the array.
printf("%d\n", p[0]); //10
printf("%d\n", p[1]); //11
printf("%d\n", p[2]); //12
What you did was getting the address of the array-"pointer" this yields the address of the first element of the array. Because &a == a
This gets written to the first element of your pointer array leaving you with
p[0] == a
p[1] == unknown
p[2] == unknown
by doing *p[0] you get the first element of p (p[0]) and dereference it *.
This is the same as *a or a[0].
But by doing *p[1] you get to an unkown memory location(p[1]) and derefence it *. This is undefined behaviour.

Can't Understand this simple code output

Code:
int a = 5;
int *ptr;
ptr = &a;
printf("%d",*ptr);
printf("\n%d",*(ptr++));
printf("\n%d",(*ptr)++);
printf("\n%d",++(*ptr));
Output:
5
5
1638268
1638268
and I am expecting the output to be:
5
junk
5
7
Sory, my pointer and operator precedence concept is very bleak. Can't understand this simple ouput.
The first is obviously 5, just dereferencing a pointer
Still five because the postfix operator returns the pointer preincrement
3 and 4 are junk because the pointer no longer points to memory that has been assigned
If you want the second to act like you expected and print junk you can use the prefix ++ instead
int a = 5;
int *ptr;
ptr = &a;
printf("%d",*ptr); // 5 as you expected.
printf("\n%d",*(ptr++)); // 5, because the pointer is incremented after this line
printf("\n%d",(*ptr)++); // Not 5 because pointer points to another location.
printf("\n%d",++(*ptr)); // Pointer already changed, no longer pointing at 5.
int a = 5;
int *ptr;
ptr = &a; // ptr is the address of the int 5
printf("%d",*ptr); // dereferences ptr, which points to in 5
printf("\n%d",*(ptr++)); // increments ptr by one, so ptr not points to
// an int one over from wherever int 5 is in memory
// but return ptr before incrementing and then dereference it
// giving int 5
printf("\n%d",(*ptr)++); // dereference ptr, which is now one int over from 5 thanks
// to the last line, which is garbage, try
// to increment garbage by 1 after printing
printf("\n%d",++(*ptr)); // dereference ptr, which is now one int over from 5,
// try to increment garbage by one before printing
*ptr just gives the value at the location which is nothing but value of a.
*(ptr++) is equivalent to (*ptr) and then (ptr += 1) because of post increment, so first it gives the value which is used by printf and then increments the pointer so now it is pointing to junk memory .
(*ptr)++ is equivalent to (*ptr) and then (*ptr += 1), so it takes the value at junk memory and increments it.
++(*ptr) is equivalent to (*ptr) += 1 so it increments the value at the junk location, now you can see the effect of undefined behavior so you don't get the last incremented value plus one, but got the same value as the last one because of undefined behavior. On my compiler I got the last incremented value plus one.

How to increment a pointer address and pointer's value?

Let us assume,
int *p;
int a = 100;
p = &a;
What will the following code actually do and how?
p++;
++p;
++*p;
++(*p);
++*(p);
*p++;
(*p)++;
*(p)++;
*++p;
*(++p);
I know, this is kind of messy in terms of coding, but I want to know what will actually happen when we code like this.
Note : Lets assume that the address of a=5120300, it is stored in pointer p whose address is 3560200. Now, what will be the value of p & a after the execution of each statement?
First, the ++ operator takes precedence over the * operator, and the () operators take precedence over everything else.
Second, the ++number operator is the same as the number++ operator if you're not assigning them to anything. The difference is number++ returns number and then increments number, and ++number increments first and then returns it.
Third, by increasing the value of a pointer, you're incrementing it by the sizeof its contents, that is you're incrementing it as if you were iterating in an array.
So, to sum it all up:
ptr++; // Pointer moves to the next int position (as if it was an array)
++ptr; // Pointer moves to the next int position (as if it was an array)
++*ptr; // The value pointed at by ptr is incremented
++(*ptr); // The value pointed at by ptr is incremented
++*(ptr); // The value pointed at by ptr is incremented
*ptr++; // Pointer moves to the next int position (as if it was an array). But returns the old content
(*ptr)++; // The value pointed at by ptr is incremented
*(ptr)++; // Pointer moves to the next int position (as if it was an array). But returns the old content
*++ptr; // Pointer moves to the next int position, and then get's accessed, with your code, segfault
*(++ptr); // Pointer moves to the next int position, and then get's accessed, with your code, segfault
As there are a lot of cases in here, I might have made some mistake, please correct me if I'm wrong.
EDIT:
So I was wrong, the precedence is a little more complicated than what I wrote, view it here:
http://en.cppreference.com/w/cpp/language/operator_precedence
checked the program and the results are as,
p++; // use it then move to next int position
++p; // move to next int and then use it
++*p; // increments the value by 1 then use it
++(*p); // increments the value by 1 then use it
++*(p); // increments the value by 1 then use it
*p++; // use the value of p then moves to next position
(*p)++; // use the value of p then increment the value
*(p)++; // use the value of p then moves to next position
*++p; // moves to the next int location then use that value
*(++p); // moves to next location then use that value
The following is an instantiation of the various "just print it" suggestions. I found it instructive.
#include "stdio.h"
int main() {
static int x = 5;
static int *p = &x;
printf("(int) p => %d\n",(int) p);
printf("(int) p++ => %d\n",(int) p++);
x = 5; p = &x;
printf("(int) ++p => %d\n",(int) ++p);
x = 5; p = &x;
printf("++*p => %d\n",++*p);
x = 5; p = &x;
printf("++(*p) => %d\n",++(*p));
x = 5; p = &x;
printf("++*(p) => %d\n",++*(p));
x = 5; p = &x;
printf("*p++ => %d\n",*p++);
x = 5; p = &x;
printf("(*p)++ => %d\n",(*p)++);
x = 5; p = &x;
printf("*(p)++ => %d\n",*(p)++);
x = 5; p = &x;
printf("*++p => %d\n",*++p);
x = 5; p = &x;
printf("*(++p) => %d\n",*(++p));
return 0;
}
It returns
(int) p => 256688152
(int) p++ => 256688152
(int) ++p => 256688156
++*p => 6
++(*p) => 6
++*(p) => 6
*p++ => 5
(*p)++ => 5
*(p)++ => 5
*++p => 0
*(++p) => 0
I cast the pointer addresses to ints so they could be easily compared.
I compiled it with GCC.
With regards to "How to increment a pointer address and pointer's value?" I think that ++(*p++); is actually well defined and does what you're asking for, e.g.:
#include <stdio.h>
int main() {
int a = 100;
int *p = &a;
printf("%p\n",(void*)p);
++(*p++);
printf("%p\n",(void*)p);
printf("%d\n",a);
return 0;
}
It's not modifying the same thing twice before a sequence point. I don't think it's good style though for most uses - it's a little too cryptic for my liking.
Note:
1) Both ++ and * have same precedence(priority), so the associativity comes into picture.
2) in this case Associativity is from **Right-Left**
important table to remember in case of pointers and arrays:
operators precedence associativity
1) () , [] 1 left-right
2) * , identifier 2 right-left
3) <data type> 3 ----------
let me give an example, this might help;
char **str;
str = (char **)malloc(sizeof(char*)*2); // allocate mem for 2 char*
str[0]=(char *)malloc(sizeof(char)*10); // allocate mem for 10 char
str[1]=(char *)malloc(sizeof(char)*10); // allocate mem for 10 char
strcpy(str[0],"abcd"); // assigning value
strcpy(str[1],"efgh"); // assigning value
while(*str)
{
cout<<*str<<endl; // printing the string
*str++; // incrementing the address(pointer)
// check above about the prcedence and associativity
}
free(str[0]);
free(str[1]);
free(str);

Resources