0

Here is the code:

int a=256;
char *x= (char *)&a;
*x++ = 1;
*x =x[0]++;
printf("a=%d\n", a);

The output is:

a=257
  • 2
    Which part is unclear to you? Do you think the output should be different? If so, why? – Andreas Wenzel Jul 21 '22 at 00:39
  • i didn't quite understand this part: `char *x= (char *)&a;` – elmahdi_gaga Jul 21 '22 at 00:42
  • That line will take the address of `a`, giving you a pointer to an `int`. This pointer to an `int` will then be cast (i.e. converted) to a pointer to a `char`, so that this pointer points to the first byte of the `int`. This pointer will then be stored in the pointer `x`. – Andreas Wenzel Jul 21 '22 at 00:46
  • 2
    The output indicates that you are running this on a system that uses little-endian integers. On systems that use big-endian, the output will depend on the number of bits used to store `int`. – paddy Jul 21 '22 at 00:49
  • 3
    Note that the result of this is implementation-dependent, because it depends on the endianness of integer storage. – Barmar Jul 21 '22 at 00:49
  • 5
    @Barmar I'm pretty sure `*x =x[0]++;` is UB. See https://stackoverflow.com/questions/9943697/whats-the-reason-for-letting-the-semantics-of-a-a-be-undefined – Andrew Henle Jul 21 '22 at 01:24
  • 2
    Was this code generated using a random character generator, or did someone assign it to you? Either way, it's just about completely meaningless in total, and therefore *very* difficult to explain or understand. There are better ways to learn C than beating your head against brick walls like this one. – Steve Summit Jul 21 '22 at 02:20

2 Answers2

2

int a=256;

Initialized integer variable with value 256. On little-endian machine memory layout is:

00 01 00 00 ...

char *x= (char *)&a;

x is pointer to least significant byte of a (on little endian machine).

00 01 00 00 ...
 ^ -- x points here

*x++ = 1;

Set byte where x points to 1, then move x to next byte. Memory is:

01 01 00 00 ...
    ^-- x points here

*x =x[0]++;

Unspecified behaviour, *x and x[0] are equal (x[0] is *(x+0)) . Post-increment is ignored in your implementation.

UPD: actually it is not ignored but overwritten by assignment. x[0]++ increases second byte:

01 02 00 00
    ^ -- x

and then value taken before increment (01) placed to the same place by *x=

01 01 00 00
dimich
  • 1,305
  • 1
  • 5
  • 7
  • 1
    *actually it is not ignored but overwritten by assignment.* Today, it is. In a week or two, with the phase of the moon different, the result might change. Or you can compile with different options, or change the code in other ways, and get a different result. I'm pretty sure `*x =x[0]++;` is undefined behavior. – Andrew Henle Jul 21 '22 at 01:27
  • 1
    @AndrewHenle it's definetly undefined (or unspecified?) behaviour. I just explained why value don't change. Of course, should never rely on this. – dimich Jul 21 '22 at 01:32
  • 2
    @dimich it is undefined behaviour – M.M Jul 21 '22 at 02:44
2

I'm going to take the posted code one line at a time.

int a=256;

I presume this is straightforward enough.

char *x= (char *)&a;

This sets a char pointer to point to just one byte of the multi-byte int value. This is a low-level, machine-dependent, and not necessarily meaningful operation. (Also x is a poor, unidiomatic name for a pointer variable.)

*x++ = 1;

This both sets the byte pointed to by x, and increments x to point to the next byte. In general that's a sensible operation — for example, it's how we often fill characters into a text buffer one at a time. In this context, though, it's borderline meaningless, because it's rare to move along the bytes of an int variable one at a time, setting or altering them.

*x =x[0]++;

And then this line is the kicker. I can't explain what it does, in fact no one can explain what it does, because it's undefined. More on this below.

printf("a=%d\n", a);

Obviously this prints the value of a, although after what poor a has been through, it's hard to say what kind of bloody mess might be left of its bits and bytes.


And now let's take a second look at that line

*x =x[0]++;

One thing we can say is that by the rules of pointer arithmetic, the subexpressions *x and x[0] are identical, they do exactly the same thing, they access the value pointed to by x. So whatever value is pointed to by x, this expression tries to modify it twice: once when it says x[0]++, and then a second time when it says *x = … to assign something to *x. And when you have one expression that tries to modify the same thing twice, that's poison: it leads to undefined behavior, and once you're in undefined behavior territory, you can't say — no one can say — what your program does.

In fact, I tried your code under two different compilers, and I got two different answers! Under one compiler the code printed 257, as yours did, but under the other compiler it printed 513. How can that be? What's the right answer? Well, in the case of undefined behavior, since there is no one right answer, it's not wrong — in fact it's more or less expected — for different compilers to give different results.

You can read much more about undefined behavior, and undefined expressions like this one, at the canonical SO question on this topic, Why are these constructs using pre and post-increment undefined behavior? Your expression is equivalent to the classic one i = i++ which is specifically discussed in several of the answers to that other question.

Steve Summit
  • 45,437
  • 7
  • 70
  • 103