So basically, the output is 1234 1234
, because:
++
has a higher precedence than *
, the postifx ++
is applied to the pointer, not the value it's pointing to
ptr
will be incremented, but again: postfix, so printf
will receive the current value ptr
is pointing to (*ptr
), which is the same as val
ptr++
is risky business. as @EOF pointed out, pointing "one past the last element in an array" or even valid object + 1 results in a valid pointer. True enough, but AFAIk, dereferencing that pointer is unspecified behaviour at the very least, I'd argue there's a risk of UB even.
Put simply, your printf("%d %d\n", val, *ptr++)
statement is equivalent to writing:
printf("%d %d\n", val, *ptr);
++ptr;//shift pointer to &val + 1
Now this won't cause any problems as such. It depends on what you do with ptr
after incrementing it. You can move a pointer to point to 1 position past an object, and that memory will be treated as a value of the same time containing a random value.
From what I gather, the C99 standard doesn't specify any behaviour WRT dereferencing this pointer. Best case scenario: it will yield a junk value. Possibly it will yield undefined behaviour depending on the type of the pointer, and the value being a trap representation.
Most types have trap representations, AFAIK all of them apart from unsigned char
do. Trap representations are defined as follows (C99 6.2.6 Representations of types)
Certain object representations need not represent a value of the
object type. If the stored value of an object has such a
representation and is read by an lvalue expression that does not have
character type, the behavior is undefined. If such a representation
is produced by a side effect that modifies all or any part of the
object by an lvalue expression that does not have character type, the
behavior is undefined.[41] Such a representation is called a trap
representation.
And the footnote
[41] Thus, an automatic variable can be initialized to a trap
representation without causing undefined behavior, but the value
of the variable cannot be used until a proper value is stored in
it.
Because a variable holding a trap representation is not a problem, having a pointer point to O+1 is perfectly fine, but using that value is a different matter.
As EOF again pointed out, the C11 standard is more specific: The resulting pointer cannot be dereferenced safely, irrespective of the type posing a risk WRT trap representations: If the result points one past the last element of the array object, it shall not be used as the operand of a unary * operator that is evaluated (reference in EOF's comment).
But back to your question:
So if you want the output 1234 1235
, the easiest way to go would be this:
#include <stdio.h>
int main ( void )
{
int i = 123, *p = &i;
printf("%d %d\n", i, i+1);
printf("%d %d\n", *p, *p + 1);//using pointers
return 0;
}
Incrementing a value using a pointer, and printing its old value, followed by the new value is not possible in a single line, because of the lack of sequence points. There is a sequence point just before the arguments are passed to the function, so writing printf("%d %d\n", i, ++(*p));
would print 1235 1235.
It's important to understand that there's no specific order in which expressions will be evaluated. If you tried to do something weird like this:
int i = 8, *p = &i;
printf("%d %d %d\n", ++(*p), printf("%d", *p), ++(*p));
It still is not possible to predict the output reliably. Possible outputs are:
- 810 1 10: the inner
printf
call was evaluated first, hence the 8
- 910 1 10: the inner call was the second expression to be evaluated (9)
- 1010 2 10: the inner call was evaluated last (10)