I've read about it and I mostly get it, but this situation confused me a bit. Why don't we use arrow operator -> in scanf? I understand that dot is used for objects and arrow for pointers but here, g is a pointer to structure.
DOCUMENT *take(int *pn){
DOCUMENT *g;
printf("How much documents? ");
scanf("%d", pn);
g = (DOCUMENT *)calloc(*pn, sizeof(DOCUMENT));
for (int i = 0; i < *pn; i++)
{
printf("Type in author, name of document and number of pages: ");
scanf("%s %s %d", g[i].author, g[i].name, &g[i].s );
}
return g;
}
The array index operator [] has a dereference built into it.
g[i] is exactly the same as *(g + i). So g[i] refers to a DOCUMENT, not a DOCUMENT * and thus you use the member access operator . instead of the pointer-to-member operator ->.
If the left operand of the . or -> is a pointer, then you use ->. Otherwise if it is an object (plain variable), then you use ..
In this case g[i] is taking a pointer and doing array subscripting on it. The result of that is an object ("lvalue"), not a pointer, hence g[i]..
Also note operator precedence in expressions like &g[i].s. The array subscripting operator [] and the struct member operator . have same operator precedence - they belong to the same group of postfix operators. But that group has left-to-right operator associativity so [] takes precedence over the .. Then after those two follow &, the unary address operator, with lowest operator precedence in the expression. So operator precedence guarantees that the expression is equivalent to &((g[i]).s).
The subscript operator used with a pointer yields the object pointed to by the pointer expression. That is, for example, this expression
g[i].author
(where g[i] is the i-th element of the array of structures) is equivalent to
( g + i )->author
where g + i is a pointer that points to the i-th element of the array of structures.
The subscript operator g[i] is equivalent to the expression *( g + i ).
You may write
g[i].author
or like
( *( g + i ) ).author
or like
( g + i )->author
Thus this call of scanf
scanf("%s %s %d", g[i].author, g[i].name, &g[i].s );
can be rewritten like
scanf("%s %s %d", ( g + i )->author, ( g + i )->name, &( g + i )->s );
When you write g[i], this is actually equal to *(g + i). That is, you dereference the pointer and it becomes an object again, so you can access it with dot (.) instead of arrow (->).
Related
int main(void)
{
short arr[3][2]={3,5,11,14,17,20};
printf("%d %d",*(arr+1)[1],**(arr+2));
return 0;
}
Hi. In above code as per my understanding ,*(arr+1)[1] is equivalent to *(*(arr+sizeof(1D array)*1)+sizeof(short)*1)=>arr[1][1] i.e 14. But the program output is arr[2][0]. can someone please explain how dereferencing the array second time adds sizeof(1Darray) i.e *(*(arr+sizeof(1D array)*1)+sizeof(1D array)*1)=>arr[2][0]
From the C Standard (6.5.2.1 Array subscripting)
2 A postfix expression followed by an expression in square brackets []
is a subscripted designation of an element of an array object. The
definition of the subscript operator [] is that E1[E2] is identical to
(*((E1)+(E2))). Because of the conversion rules that apply to the
binary + operator, if E1 is an array object (equivalently, a pointer
to the initial element of an array object) and E2 is an integer,
E1[E2] designates the E2-th element of E1 (counting from zero).
So the expression
*(arr+1)[1]
can be rewritten like
* ( *( arr + 1 + 1 ) )
that is the same as
*( *( arr + 2 ) )
arr + 2 points to the third "row" of the array. Dereferencing the pointer expression you will get the "row" itself of the type short[2] that used in the expression *( arr[2] ) is converted to pointer to its first element. So the expression equivalent to arr[2][0] yields the value 17.
Thus these two expressions
*(arr+1)[1],
and
**(arr+2)
are equivalent each other.
Note: pay attention to that there is a typo in your code
printf("%d %d",*(arr+1)[1],**(arr+2);
You need one more parenthesis
printf("%d %d",*(arr+1)[1],**(arr+2) );
I am trying to find the number of digits in a given number through the use of pointers.
This code below will give the correct output,
void numDigits(int num, int *result) {
*result = 0;
do {
*result += 1;
num = num / 10;
} while (num > 0);
}
However, if I change the *result += 1; line to *result++;, the output will no longer be correct and only give 0.
What is going on here?
In C/C++, precedence of Prefix ++ (or Prefix --) has higher priority than dereference (*) operator, and precedence of Postfix ++ (or Postfix --) is higher than both Prefix ++ and *.
If p is a pointer then *p++ is equivalent to *(p++) and ++*p is equivalent to ++(*p) (both Prefix ++ and * are right associative).
*result++ is interpreted as *(result++).
the order of evaluation is the increment is first, then you dereference the pointer, the value of the pointer stays the same for the line in the expression if it's a postfix.
what you are trying to do is to increment the dereference of the pointer so you need to put the parenthesis on the dereference then increment it, like this: (*result)++;
This question already has answers here:
With arrays, why is it the case that a[5] == 5[a]?
(20 answers)
Closed 3 years ago.
Today I stumbled over a C riddle that got a new surprise for me.
I didn't think that -1[p] in the example below would compile, but it did. In fact, x ends up to be -3.
int x;
int array[] = {1, 2, 3};
int *p = &array[1];
x = -1[p];
I searched the internet for something like -1[pointer] but couldn't find anything. Okay, it is difficult to enter the correct search query, I admit. Who knows why -1[p] compiles and X becomes -3?
I'm the person that made this "riddle" (see my Twitter post)
So! What's up with -1[p]?
ISO C actually defines [] to be symmetrical, meaning x[y] is the same as y[x], where x and y are both expressions.
Naively, we could jump to the conclusion that -1[p] is therefore p[-1] and so x = 1,
However, -1 is actually the unary minus operator applied to the constant 1, and unary minus has a lower precedence than []
So, -1[p] is -(p[1]), which yields -3.
This can lead to funky looking snippets like this one, too:
sizeof(char)["abc"] /* yields 'b' */
First thing to figure out is the precedence. Namely [] has higher precedence than unary operators, so -1[p] is equal to -(1[p]), not (-1)[p]. So we're taking the result of 1[p] and negating it.
x[y] is equal to *(x+y), so 1[p] is equal to *(1+p), which is equal to *(p+1), which is equal to p[1].
So we're taking the element one after where p points, so the third element of array, i.e. 3, and then negating it, which gives us -3.
According to the C Standard (6.5.2 Postfix operators) the subscript operator is defined the following way
postfix-expression [ expression ]
So before the square brackets there shall be a postfix expression.
In this expression statement
x = -1[p];
there is used the postfix expression 1 (that is at the same time a primary expression), the postfix expression 1[p] (that is the subscript operator) and the unary operator - Take into account that when the compiler splits a program into tokens then integer constants are considered as tokens themselves without the minus. minus is a separate token.
So the statement can be rewritten like
x = -( 1[p] );
because a postfix expression has a higher priority than an unary expression.
Let's consider at first the postfix sub-expression 1[p]
According to the C Standard (6.5.2.1 Array subscripting)
2 A postfix expression followed by an expression in square brackets []
is a subscripted designation of an element of an array object. The
definition of the subscript operator [] is that E1[E2] is identical to
(*((E1)+(E2))). Because of the conversion rules that apply to the
binary + operator, if E1 is an array object (equivalently, a pointer
to the initial element of an array object) and E2 is an integer,
E1[E2] designates the E2-th element of E1 (counting from zero).
So this sub-expression evaluates like *( ( 1 ) + ( p ) ) and is the same as *( ( p ) + ( 1 ) ).
Thus the above statement
x = -1[p];
is equivalent to
x = -p[1];
and will yield -3, because the pointer p points to the second element of the array due to the statement
int *p = &array[1];
and then the expression p[1] yields the value of the element after the second element of the array. Then the unary operator - is applied.
This
int array[] = {1, 2, 3};
looks like
array[0] array[1] array[2]
--------------------------
| 1 | 2 | 3 |
--------------------------
0x100 0x104 0x108 <-- lets assume 0x100 is base address of array
array
Next when you do like
int *p = &array[1];
the integer pointer p points to address of array[1] i.e 0x104. It looks like
array[0] array[1] array[2]
--------------------------
| 1 | 2 | 3 |
--------------------------
0x100 0x104 0x108 <-- lets assume 0x100 is base address of array
|
p holds 0x104
And when you do like
x = -1[p]
-1[p] is equivalent to -(1[p]) i.e -(p[1]). it looks like
-(p[1]) ==> -(*(p + 1*4)) /* p holds points to array[1] i.e 0x104 */
==> -(*(0x104 + 4))
==> -(*(0x108)) ==> value at 0x108 is 3
==> prints -3
What happens here is really interesting.
p[n] means *(p+n). Thats why you see 3, because "p" points to array[1] which is 2, and -p[1] is interpreted as -(*(p+1)) which is -3.
Expression is:
foo = *p++
I am looking for a guide/reference with examples that can explain these things.
I understand postfix ++ has higher precedence than indirection *, so the expression is parsed as
*(p++)
But I am trying to get more clarity on the statement in GNU C reference manual Pg 40, that says:
Here p is incremented as a side effect of the expression, but foo takes the value of *(p++) rather than (*p)++, since the unary operators bind right to left.
In C/C++, precedence of Prefix ++ (or Prefix –) and dereference (*) operators is same, and precedence of Postfix ++ (or Postfix –) is higher than both Prefix ++ and *.
If p is a pointer then *p++ is equivalent to *(p++) (because postfix has higher precedence)
++*p is equivalent to ++(*p) (both Prefix ++ and * are right associative).
*++p is equivalent to *(++p) (both Prefix ++ and * are right associative).
You can see the below 2 programs to clarify your doubt.
Program 1
#include<stdio.h>
int main()
{
char arr[] = "overflow";
char *p = arr;
++*p;
printf(" %c", *p);
getchar();
return 0;
}
Output: p
Program 2
#include<stdio.h>
int main()
{
char arr[] = "overflow";
char *p = arr;
*p++;
printf(" %c", *p);
getchar();
return 0;
}
Output: v
The GNU quote is misleading (IMHO); from a language point-of-view it's nothing to do with left-to-right (or vice versa).*
The C language standard doesn't define things in terms of precedence or associativity (left-to-right or right-to-left); these are merely implied by the defined grammar. Postfix ++ is classified as a postfix-expression rather than a unary-expression:
postfix-expression:
primary-expression
[...]
postfix-expression ++
postfix-expression --
[...]
unary-expression:
postfix-expression
++ unary-expression
-- unary-expression
unary-operator cast-expression
[...]
unary-operator:
& * + - ~ !
The interaction of the above production rules mean that your example is interpreted as *(p++).
In non-standardese, though, the reason is due to precedence, not associativity (which makes little sense for unary operators).
* In fact, the postfix operators are effectively left-to-right, which is the opposite of what's claimed.
The OP asked "how is evaluated" the expression *p++.
One thing is precedence and another different thing is evaluation.
The expression p++ increments the value of the variable p, but the value of the expression is he "old" value that p had.
For example, consider that p is char pointer used to analyze a string:
char s[] = "0123456789!";
char *p = s;
char q;
p = s; // Here *p == '0'
q = *p++ // Here q == '0' but *p == '1'
Although the precedence rules imply that *p++ is the same that *(p++), the value of *p++ is s[0], in despite of p == &s[1].
To be more precise, the value of the expression is the same as of *p.
In this case, the "side effects" are referring to the operations that are done over the objects, in this case we have the objects p and q in the expression q = *p++.
"Operation over objects" are not walking in the same path that "evaluation of expressions".
Saying that postfix and unary operators are right-associative (bind right to left) is just another way to express the fact that postfix operators have higher precedence in C than unary operators.
I am confused of operator precedence table give in http://www.difranco.net/compsci/C_Operator_Precedence_Table.htm
I mean right-to-left and left-to-right.
I want to know in what order the operator will we applied on this code.
int main()
{
int i[] = {3, 5};
int *p = i;
int j = --*p++;
printf("j = %d\n\n", j);
system("pause");
return 0;
}
Is it like --(*(p++))? or (--(*p))++ ? Its very confusing. is there any standard rule to resolve this problem.
The expression:
j = --*p++;
is equivalent to:
j = --*p; // first decrements value pointed by p, then assign value pointer by p to j
p++; // increment p to point to next location
The parenthesis version of your expression should be : --(*(p++)); Read #Jonathan Leffler's answer.
I would also suggest you to read #Eric Lippert answer: Incrementing Pointers, Exact Sequence to understand ++ and * operator expression that how a compiler can perform it at low level.
I am confused by the operator precedence table give in http://www.difranco.net/compsci/C_Operator_Precedence_Table.htm. What does right-to-left and left-to-right mean in this table?
Precedence and associativity determine how the parentheses are logically inserted into an underparenthesized expression. If you have
x + y * z
then * is higher precedence, so it wins, and this is:
x + (y * z)
not
(x + y) * z
If you have two operators that have the same precedence then which one wins depends on the associativity. + and - are the same precedence and have left-to-right associativity, so
x + y - z
is
(x + y) - z
And not
x + (y - z)
Operators with right-to-left associativity put the parentheses on the rightmost expression first.
I want to know in what order the operator will we applied on this code. --*p++
Well, follow the chart. We have *, prefix decrement and postfix increment. Consult the precedence table first. Postfix increment is higher precedence than the other two, so automatically this is --*(p++). And now we do not need to consult the table to work out the rest; clearly the only possible parenthesization is --(*(p++)).
++ and -- Prefix increment/decrement right-to-left
and later on you found *
j = --*p++;
Above statement according to precedence -- will perform first. So in expression -- is pre-decrement on *p and then ++ is post increment, will increment pointer p.
j= --*p; //and immediately do *p++ == p++ , because here ++ got priority. and this is post decrement this wont assign to j.this as same as incrementing p value in next statement.
p++;
There are plenty of tricks on prefix increment and postfix increment.
As a programmer, you do not need to spend too much time on those tricks, just use brackets in your code to show the computing order.