-7
  #include<stdio.h>
main()
{
    int val=1234;
    int* ptr=&val;
    printf("%d %d",val,*ptr++);
}



out of my knowledge i would manually get 1235 1234,

*ptr++ would give 1234 as output and 1235 in memory after that val variable would print 1235 . later I've realized my opinion on this would be wrong,after ideone it.plz correct me where i was wrong ,it shows output as 1234 1234

Azhagu Surya
  • 132
  • 1
  • 1
  • 17
  • `*ptr++` does not increment the object pointed to by `ptr`, it increments *the pointer*. – EOF Jun 13 '16 at 16:28
  • @EliasVanOotegem: There is no undefined behavior here. – EOF Jun 13 '16 at 17:01
  • @EliasVanOotegem: You are allowed to point one past the last element of an array, including an array of one element. – EOF Jun 13 '16 at 17:03
  • 2
    @EliasVanOotegem C11 draft standard n1570: *6.5.6 Additive operators 7 For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.* – EOF Jun 13 '16 at 17:05
  • http://stackoverflow.com/questions/8208021/how-to-increment-a-pointer-address-and-pointers-value – mssirvi Jun 13 '16 at 17:06
  • @EOF: True, the pointer is allowed to exist, but what about dereferencing it? The resulting pointer points to an unrelated object of the array's type, int trap representations could yield undefined behaviour. AFAIK, the behaviour of dereferencing a pointer of O+1 is not specified (in C99 standard at least), and I'd say there's a chance of UB – Elias Van Ootegem Jun 13 '16 at 17:17
  • @EliasVanOotegem: The incremented pointer is not dereferenced in the OP's code. Note that `*ptr++` is *postfix-increment*, not *prefix-increment*. In contrast, `*++ptr` *would be* undefined. – EOF Jun 13 '16 at 17:21
  • @EOF: That's what I meant when I said _"It's what comes after that is the problem"_. Agreed that the current behaviour can be explained, I just wanted to point out that `*ptr++` is risky business – Elias Van Ootegem Jun 13 '16 at 17:25
  • 1
    @EliasVanOotegem You started out claiming that this was undefined behavior. Stop moving the goalposts and admit that you were wrong. – EOF Jun 13 '16 at 17:26
  • @EOF I was wrong, fair enough. Did learn some interesting stuff because of it – Elias Van Ootegem Jun 13 '16 at 17:39
  • @EliasVanOotegem That's a nice outcome for a fairly bad question. – EOF Jun 13 '16 at 17:43

3 Answers3

1

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 chardo. 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)
Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
  • While most types *may* have trap representations, it's not at all required that they *do*. For integer/pointer types, I'm not aware of any architecture but IA64 that has trap representations in hardware. Also, accessing beyond the end of the array is undefined *regardless* of whether there are trap representations: C11 draft standard n1570, *6.5.6 Additive operators 8 [...] 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.* Finally, `+1` for the best answer to the question so far. – EOF Jun 13 '16 at 17:57
  • Actually, the final sentence in this answer is wrong. `printf("%d %d\n", i, ++(*p));` Is *undefined*, because the order of evaluation of function arguments is unspecified. – EOF Jun 13 '16 at 18:16
  • @EOF: thanks, will update the answer. I'll be more specific WRT that last sentence. The order in which the expressions are evaluated is indeed undefined, but they're all guaranteed to be evaluated before entering the `printf` call, so using the prefix `++` operator does guarantee the output 1235 1235 no? – Elias Van Ootegem Jun 13 '16 at 19:31
  • 1
    No. A simple way to see it is this: after `int i; int *p = &i`, `i` and `*p` refer to *the same* object. Thus, `printf("%d %d\n", i, ++(*p));` is the same as `printf("%d %d\n", i, ++i);`. Now imagine the argument `i` were evaluated before the argument `++i`. In that case, the result would be two different numbers printed. On the other hand, if `++i` were evaluated first, the same number would be printed twice. The C standard says it's *undefined behavior*. – EOF Jun 13 '16 at 22:19
  • 1
    The new case you present is even more convoluted: `printf("%d %d %d\n", ++(*p), printf("%d", *p), ++(*p));` contains side effects on scalar values that are unsequenced with regard to function calls using those scalars. The C standard has special cases for this, guaranteeing that operator `++` is evaluated atomically with regard to such an unsequenced function call, but not which happens before the other. Honestly this is beyond my expertise. I can only warn against this kind of construct. – EOF Jun 13 '16 at 22:23
0

while parsing an expression, an operator with the higher precedence will be bounded tighter to its arguments as similar to parenthesis.

so *ptr++ is parsed as *(ptr++).

the output of your program is 1234 1234, because of post increment operator. So the initial value 1234 is returned.

mssirvi
  • 147
  • 3
  • 14
-1

You must not mix up (*ptr)++ and *ptr++. The programs will have different outputs:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include<stdio.h>
main()
{
    int val=1234;
    int* ptr=&val;
    printf("%d %d",val,(*ptr)++);
}

Output

1235 1234

Program 2

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include<stdio.h>
main()
{
    int val=1234;
    int* ptr=&val;
    printf("%d %d",val,*ptr++);
}

Output

1234 1234
Niklas Rosencrantz
  • 25,640
  • 75
  • 229
  • 424