Velocity Reviews > Can somebody explain to me the output of the following code?

# Can somebody explain to me the output of the following code?

asdfghjk
Guest
Posts: n/a

 08-18-2010
#include <stdio.h>
main()
{
struct Data
{
int a;
int b;
} y[4] = { 1, 10, 3, 30, 2, 20, 4, 40};
struct Data *x = y;
int i;
for(i=0; i<4; i++)
{
x->a = x->b, ++x++->b;
printf("%d %d\t", y[i].a, y[i].b);
}
}

I have confusion regarding the ++x++->b part.
The output is : 10 11 30 31 20 21 40 41

Chris H
Guest
Posts: n/a

 08-18-2010
In message <(E-Mail Removed)
s.com>, asdfghjk <(E-Mail Removed)> writes
>#include <stdio.h>
>main()
>{
> struct Data
> {
> int a;
> int b;
> } y[4] = { 1, 10, 3, 30, 2, 20, 4, 40};
> struct Data *x = y;
> int i;
> for(i=0; i<4; i++)
> {
> x->a = x->b, ++x++->b;
> printf("%d %d\t", y[i].a, y[i].b);
> }
>}
>
>I have confusion regarding the ++x++->b part.
>The output is : 10 11 30 31 20 21 40 41

See and click at the bottom to se the answers. It is a bit old now but

http://www.phaedsys.demon.co.uk/chri...swengtips3.htm

--
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
\/\/\/\/\ Chris Hills Staffs England /\/\/\/\/
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/

Mark Bluemel
Guest
Posts: n/a

 08-18-2010
asdfghjk wrote:
> #include <stdio.h>
> main()
> {
> struct Data
> {
> int a;
> int b;
> } y[4] = { 1, 10, 3, 30, 2, 20, 4, 40};
> struct Data *x = y;
> int i;
> for(i=0; i<4; i++)
> {
> x->a = x->b, ++x++->b;
> printf("%d %d\t", y[i].a, y[i].b);
> }
> }
>
> I have confusion regarding the ++x++->b part.

Not surprisingly, as I'm sure that was the originator's intention.

Here's how I understand the line "x->a = x->b, ++x++->b;"

We have two expressions separated by a "," (remember that an assignment
is itself an expression). The expressions are evaluated left to right,
and the rightmost is the value of the expression as a whole - which in
this case (and probably most cases) we ignore.

The first expression is "x->a = x->b" which is fairly self-explanatory.
So the first time through the loop, the value 1 is replaced by the value 10.

The second expression "++x++->b" does far too many things, IMHO. The
pre-increment operates on the integer "x->b" (turning 10 to 11), while
the post-increment operates on x, moving it on in step with the indexing
in the loop. The value returned by the expression (which is again
ignored) is the incremented value of "x->b".

> The output is : 10 11 30 31 20 21 40 41

Mark Bluemel
Guest
Posts: n/a

 08-18-2010
Chris H wrote:
> In message <(E-Mail Removed)
> s.com>, asdfghjk <(E-Mail Removed)> writes
>> #include <stdio.h>
>> main()
>> {
>> struct Data
>> {
>> int a;
>> int b;
>> } y[4] = { 1, 10, 3, 30, 2, 20, 4, 40};
>> struct Data *x = y;
>> int i;
>> for(i=0; i<4; i++)
>> {
>> x->a = x->b, ++x++->b;
>> printf("%d %d\t", y[i].a, y[i].b);
>> }
>> }
>>
>> I have confusion regarding the ++x++->b part.
>> The output is : 10 11 30 31 20 21 40 41

>
> See and click at the bottom to se the answers. It is a bit old now but
>
> http://www.phaedsys.demon.co.uk/chri...swengtips3.htm
>

Hmmm... I'm not convinced

That page claims that
<Quote>
uint16_t i = 10;
uint16_t j = 0;

j=2;
printf("i = %d, j = %d, i * j++ = %d \n", i, j, i* j++ );

The code is effectively running the following calculation - "I=10, j=3,
I * j++"

</Quote>

Firstly, I don't see why "uint16_t" is used in preference to plain
"int", especially since "%d" in printf requires int...

Secondly, I'm fairly sure that the explanation makes some major
assumptions about the order of evaluation of function arguments, which
aren't necessarily true.

Am I mistaken?

Ben Bacarisse
Guest
Posts: n/a

 08-18-2010
Chris H <(E-Mail Removed)> writes:

> In message <(E-Mail Removed)
> s.com>, asdfghjk <(E-Mail Removed)> writes
>>#include <stdio.h>
>>main()

int main(void) is better. Given that main returns an int a return 0; is
a good idea too.

>>{
>> struct Data
>> {
>> int a;
>> int b;
>> } y[4] = { 1, 10, 3, 30, 2, 20, 4, 40};
>> struct Data *x = y;
>> int i;
>> for(i=0; i<4; i++)
>> {
>> x->a = x->b, ++x++->b;

To the OP, a hint. It helps if you know how this is parsed. All
postfix operators bind more tightly than all prefix operators so this is

++( (x++)->b )

Does that help?

>> printf("%d %d\t", y[i].a, y[i].b);
>> }
>>}
>>
>>I have confusion regarding the ++x++->b part.
>>The output is : 10 11 30 31 20 21 40 41

>
> See and click at the bottom to se the answers. It is a bit old now but
>
> http://www.phaedsys.demon.co.uk/chri...swengtips3.htm

I don't see the connection between that page and the OP's code. All
your examples are undefined (though you never say that for some reason)
but I think the OP's code is well-defined (though ghastly).

--
Ben.

Ben Bacarisse
Guest
Posts: n/a

 08-18-2010
Mark Bluemel <(E-Mail Removed)> writes:

> Chris H wrote:
>> In message <(E-Mail Removed)
>> s.com>, asdfghjk <(E-Mail Removed)> writes
>>> #include <stdio.h>
>>> main()
>>> {
>>> struct Data
>>> {
>>> int a;
>>> int b;
>>> } y[4] = { 1, 10, 3, 30, 2, 20, 4, 40};
>>> struct Data *x = y;
>>> int i;
>>> for(i=0; i<4; i++)
>>> {
>>> x->a = x->b, ++x++->b;
>>> printf("%d %d\t", y[i].a, y[i].b);
>>> }
>>> }
>>>
>>> I have confusion regarding the ++x++->b part.
>>> The output is : 10 11 30 31 20 21 40 41

>>
>> See and click at the bottom to se the answers. It is a bit old now but
>>
>> http://www.phaedsys.demon.co.uk/chri...swengtips3.htm
>>

>
> Hmmm... I'm not convinced
>
> That page claims that
> <Quote>
> uint16_t i = 10;
> uint16_t j = 0;
>
> j=2;
> printf("i = %d, j = %d, i * j++ = %d \n", i, j, i* j++ );
>
> The code is effectively running the following calculation - "I=10,
> j=3, I * j++"
>
> </Quote>
>
> Firstly, I don't see why "uint16_t" is used in preference to plain
> "int", especially since "%d" in printf requires int...

That will be fine on many systems because uint16_t will promote to int
when passed to printf but it does seem odd that, after including
inttypes.h, the correct format was not used (PRIu16).

As you say, for illustration, int would be much simpler.

> Secondly, I'm fairly sure that the explanation makes some major
> assumptions about the order of evaluation of function arguments, which
> aren't necessarily true.
>
> Am I mistaken?

I think all the examples are "potentially" undefined (I may have missed
a defined one) in that they all might read the prior value of j (for a
purpose other than determining the new value for j) without an
intervening sequence point.

I say "potentially" undefined because I suppose that if the change in j
happens before any other "read" of j, the prior value is not being read,
only the new one is. I'd still say "undefined" as a genaral answer
since from the C point of view you can't be sure to avoid it.

--
Ben.

Shao Miller
Guest
Posts: n/a

 08-18-2010
On Aug 18, 12:05*pm, Mark Bluemel <(E-Mail Removed)> wrote:
> Chris H wrote:
> > See *and click at the bottom to se the answers. *It is a bit old now but

>
> >http://www.phaedsys.demon.co.uk/chri...swengtips3.htm

>
> Hmmm... I'm not convinced
>
> That page claims that
> <Quote>
> uint16_t i = 10;
> uint16_t j = 0;
>
> j=2;
> printf("i = %d, j = %d, i * j++ = %d \n", i, j, i* j++ );
>
> The code is effectively running the following calculation - "I=10, j=3,
> I * j++"
>
> </Quote>
>
> Firstly, I don't see why "uint16_t" is used in preference to plain
> "int", especially since "%d" in printf requires int...
>
> Secondly, I'm fairly sure that the explanation makes some major
> assumptions about the order of evaluation of function arguments, which
> aren't necessarily true.
>
> Am I mistaken?

I think the matter of 'printf' with the 'j++' was recently covered in
Modification of 'j' but a read of 'j' in another argument could be
considered to be a violation of C99's section 6.5, paragraph 2;
leading to undefined behaviour. A compiler could refuse to translate
the source code. At run-time, some extremely unexpected results are
allowed of a conforming implementation.

Ben Bacarisse
Guest
Posts: n/a

 08-18-2010
Ben Bacarisse <(E-Mail Removed)> writes:
<snip>
Code example: printf("%d\n", (i * j--) + (i * j));

> I think all the examples are "potentially" undefined (I may have missed
> a defined one) in that they all might read the prior value of j (for a
> purpose other than determining the new value for j) without an
> intervening sequence point.
>
> I say "potentially" undefined because I suppose that if the change in j
> happens before any other "read" of j, the prior value is not being read,
> only the new one is. I'd still say "undefined" as a genaral answer
> since from the C point of view you can't be sure to avoid it.

I take this last "potentially" bit back and revert to my original reply
to Chris H. It is, at best, a sort of C sophistry at worst plain wrong.
The code is undefined.

I think any reference to the object that is changing will constitute a
read of the "prior value" from the C standard point of view even if an
implementation ensures that the change has, in practise, happened. Only
at the next sequence point does the prior value change to being "the
value" of the object.

--
Ben.

Andrey Tarasevich
Guest
Posts: n/a

 08-18-2010
Mark Bluemel wrote:
> Hmmm... I'm not convinced
>
> That page claims that
> <Quote>
> uint16_t i = 10;
> uint16_t j = 0;
>
> j=2;
> printf("i = %d, j = %d, i * j++ = %d \n", i, j, i* j++ );
>
> The code is effectively running the following calculation - "I=10, j=3,
> I * j++"
>
> </Quote>
>
> Firstly, I don't see why "uint16_t" is used in preference to plain
> "int", especially since "%d" in printf requires int...
>
> Secondly, I'm fairly sure that the explanation makes some major
> assumptions about the order of evaluation of function arguments, which
> aren't necessarily true.

The above `printf` produces undefined behavior. Making assumptions about
its order of evaluation makes no sense whatsoever.

--
Best regards.
Andrey Tarasevich

Andrey Tarasevich
Guest
Posts: n/a

 08-18-2010
asdfghjk wrote:
> #include <stdio.h>
> main()
> {
> struct Data
> {
> int a;
> int b;
> } y[4] = { 1, 10, 3, 30, 2, 20, 4, 40};
> struct Data *x = y;
> int i;
> for(i=0; i<4; i++)
> {
> x->a = x->b, ++x++->b;
> printf("%d %d\t", y[i].a, y[i].b);
> }
> }
>
> I have confusion regarding the ++x++->b part.
> The output is : 10 11 30 31 20 21 40 41

The output of this code cannot be meaningfully explained from the point
of view of C language. The `++x++` subexpression produces Undefined
Behavior, meaning that even if this code generates some output, it can
be safely perceived as essentially random.

In fact, the code is not even guaranteed to compile, since the compilers
are allowed to refuse to compile code with UB.

--
Best regards,
Andrey Tarasevich