Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > more on operands' binding and evaluation order

Reply
Thread Tools

more on operands' binding and evaluation order

 
 
Ersek, Laszlo
Guest
Posts: n/a
 
      06-21-2010
Hi,

given the following code,

#include <stdio.h>

static int *
ip_incr(int id, int **i)
{
(void)fprintf(stdout, "%d\n", id);
return ++*i;
}

int main(void)
{
int x[4] = { 0 },
*a = x,
*b = x + 1,
*c = x + 2;

*ip_incr(1, &a) = *ip_incr(2, &b) = *ip_incr(3, &c) = 7;
(void)fprintf(stdout, "%d %d %d %d\n", x[0], x[1], x[2], x[3]);
return 0;
}

am I right to think that the program is well defined, and that the output
is (provided no output error occurs)

----v----
A
B
C
0 7 7 7
----^----

where [ABC] is any permutation of [123]?

Thanks,
lacos
 
Reply With Quote
 
 
 
 
Eric Sosman
Guest
Posts: n/a
 
      06-21-2010
On 6/21/2010 8:29 AM, Ersek, Laszlo wrote:
> Hi,
>
> given the following code,
>
> #include <stdio.h>
>
> static int *
> ip_incr(int id, int **i)
> {
> (void)fprintf(stdout, "%d\n", id);
> return ++*i;
> }
>
> int main(void)
> {
> int x[4] = { 0 },
> *a = x,
> *b = x + 1,
> *c = x + 2;
>
> *ip_incr(1, &a) = *ip_incr(2, &b) = *ip_incr(3, &c) = 7;
> (void)fprintf(stdout, "%d %d %d %d\n", x[0], x[1], x[2], x[3]);
> return 0;
> }
>
> am I right to think that the program is well defined, and that the
> output is (provided no output error occurs)
>
> ----v----
> A
> B
> C
> 0 7 7 7
> ----^----
>
> where [ABC] is any permutation of [123]?


As far as I can see, yes. (Although the "any permutation"
bit clashes somewhat with "well defined.") What aspects do you
find suspicious?

--
Eric Sosman
http://www.velocityreviews.com/forums/(E-Mail Removed)lid
 
Reply With Quote
 
 
 
 
Ersek, Laszlo
Guest
Posts: n/a
 
      06-21-2010
On Mon, 21 Jun 2010, Eric Sosman wrote:

> On 6/21/2010 8:29 AM, Ersek, Laszlo wrote:
>> Hi,
>>
>> given the following code,
>>
>> #include <stdio.h>
>>
>> static int *
>> ip_incr(int id, int **i)
>> {
>> (void)fprintf(stdout, "%d\n", id);
>> return ++*i;
>> }
>>
>> int main(void)
>> {
>> int x[4] = { 0 },
>> *a = x,
>> *b = x + 1,
>> *c = x + 2;
>>
>> *ip_incr(1, &a) = *ip_incr(2, &b) = *ip_incr(3, &c) = 7;
>> (void)fprintf(stdout, "%d %d %d %d\n", x[0], x[1], x[2], x[3]);
>> return 0;
>> }
>>
>> am I right to think that the program is well defined, and that the
>> output is (provided no output error occurs)
>>
>> ----v----
>> A
>> B
>> C
>> 0 7 7 7
>> ----^----
>>
>> where [ABC] is any permutation of [123]?

>
> As far as I can see, yes. (Although the "any permutation"
> bit clashes somewhat with "well defined.")


Indeed, I should have asked if there was "no undefined behavior" in this
program.


> What aspects do you find suspicious?


I wrote the snippet for a friend in order to demonstrate the difference
between operand binding and order of evaluation. In particular that the
"right-associativity" of the assignment operator doesn't determine the
order of calls to ip_incr(). I just wanted to double-check the sanity of
my code with your help.

(BTW, compiling the program with gcc (Debian 4.3.2-1.1), ABC resolves to
123, which is the exact reverse of the "intuitive" (in fact unspecified)
order that my friend assumed (in my understanding).)

Thank you very much.
lacos
 
Reply With Quote
 
Tim Rentsch
Guest
Posts: n/a
 
      06-22-2010
"Ersek, Laszlo" <(E-Mail Removed)> writes:

> given the following code,
>
> #include <stdio.h>
>
> static int *
> ip_incr(int id, int **i)
> {
> (void)fprintf(stdout, "%d\n", id);
> return ++*i;
> }
>
> int main(void)
> {
> int x[4] = { 0 },
> *a = x,
> *b = x + 1,
> *c = x + 2;
>
> *ip_incr(1, &a) = *ip_incr(2, &b) = *ip_incr(3, &c) = 7;
> (void)fprintf(stdout, "%d %d %d %d\n", x[0], x[1], x[2], x[3]);
> return 0;
> }
>
> am I right to think that the program is well defined, and that the
> output is (provided no output error occurs)
>
> ----v----
> A
> B
> C
> 0 7 7 7
> ----^----
>
> where [ABC] is any permutation of [123]?


The program seems more complicated than it needs to be to
illustrate what I think you're trying to illustrate. However,
unless there is some obscure condition I've missed, it has no
undefined behavior.
 
Reply With Quote
 
Luca Forlizzi
Guest
Posts: n/a
 
      06-22-2010
On 21 Giu, 14:29, "Ersek, Laszlo" <(E-Mail Removed)> wrote:
> Hi,
>
> given the following code,
>
> #include <stdio.h>


nice example!
I think it has no undefined behavior, as others, more experienced than
me, have already said.
May I ask why you choose to use fprintf(stdout,...) instead of
printf ?
(Given the illustrative nature of the example, using printf may render
the code a little bit simpler)

 
Reply With Quote
 
Ersek, Laszlo
Guest
Posts: n/a
 
      06-22-2010
On Mon, 21 Jun 2010, Kenneth Brody wrote:

>>> On 6/21/2010 8:29 AM, Ersek, Laszlo wrote:


>>>> #include <stdio.h>
>>>>
>>>> static int *
>>>> ip_incr(int id, int **i)
>>>> {
>>>> (void)fprintf(stdout, "%d\n", id);
>>>> return ++*i;
>>>> }
>>>>
>>>> int main(void)
>>>> {
>>>> int x[4] = { 0 },
>>>> *a = x,
>>>> *b = x + 1,
>>>> *c = x + 2;
>>>>
>>>> *ip_incr(1, &a) = *ip_incr(2, &b) = *ip_incr(3, &c) = 7;
>>>> (void)fprintf(stdout, "%d %d %d %d\n", x[0], x[1], x[2], x[3]);
>>>> return 0;
>>>> }


> And MSVC (version 14), even with optimizations supposedly disabled
> (/Od), optimizes ip_incr() away, and generates the equivalent of:
>
> int main(void)
> {
> fprintf(stdout,"%d\n",3);
> fprintf(stdout,"%d\n",2);
> fprintf(stdout,"%d\n",1);
> fprintf(stdout,"%d %d %d %d\n",0,7,7,7);
> return 0;
> }


I was actually a bit curious what evaluation orders different compilers
choose. Thanks for the info!

lacos
 
Reply With Quote
 
Ersek, Laszlo
Guest
Posts: n/a
 
      06-22-2010
On Mon, 21 Jun 2010, Tim Rentsch wrote:

> "Ersek, Laszlo" <(E-Mail Removed)> writes:
>
>> #include <stdio.h>
>>
>> static int *
>> ip_incr(int id, int **i)
>> {
>> (void)fprintf(stdout, "%d\n", id);
>> return ++*i;
>> }
>>
>> int main(void)
>> {
>> int x[4] = { 0 },
>> *a = x,
>> *b = x + 1,
>> *c = x + 2;
>>
>> *ip_incr(1, &a) = *ip_incr(2, &b) = *ip_incr(3, &c) = 7;
>> (void)fprintf(stdout, "%d %d %d %d\n", x[0], x[1], x[2], x[3]);
>> return 0;
>> }


> The program seems more complicated than it needs to be to
> illustrate what I think you're trying to illustrate.


Yes, it is positively not "minimal". We started with

a = b = c = 7;

then (after changing types accordingly)

*++a = *++b = *++c = 7;

and then I added the fprintf()'s. There are better ways, probably. Care to
show one?


> However, unless there is some obscure condition I've missed, it has no
> undefined behavior.


Thanks!
lacos
 
Reply With Quote
 
Ersek, Laszlo
Guest
Posts: n/a
 
      06-22-2010
On Mon, 21 Jun 2010, Luca Forlizzi wrote:

> On 21 Giu, 14:29, "Ersek, Laszlo" <(E-Mail Removed)> wrote:
>> Hi,
>>
>> given the following code,
>>
>> #include <stdio.h>

>
> nice example!


Thanks


> I think it has no undefined behavior, as others, more experienced than
> me, have already said.
> May I ask why you choose to use fprintf(stdout,...) instead of
> printf ?


I like to be able to search for the stream's name.


> (Given the illustrative nature of the example, using printf may render
> the code a little bit simpler)


In general I don't believe in "simple examples", as in omitting error
handling and working in a different style than otherwise. Missing error
handling creates a false impression. Truth to be told, I don't really like
that I threw away the return values of the fprintf() calls. Once the test
program compiles, it should also honor write errors, eg.

$ ./try >/dev/full

at least with a nonzero exit status.

Cheers,
lacos
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      06-22-2010
On 6/22/2010 8:33 AM, Ersek, Laszlo wrote:
> [...]
> Yes, it is positively not "minimal". We started with
>
> a = b = c = 7;
>
> then (after changing types accordingly)
>
> *++a = *++b = *++c = 7;
>
> and then I added the fprintf()'s. There are better ways, probably. Care
> to show one?


If the goal is to show that associativity et al. do not govern
evaluation order, I'd suggest stripping away side-effects that don't
really matter and may just act as red herrings. Something like

#include <stdio.h>

static int index(int idx) {
printf ("idx = %d\n", idx);
return idx;
}

int main(void) {
int array[4] = { 0 };
array[index(1)] = array[index(2)] = array[index(3)] = 7;
printf ("array = { %d, %d, %d, %d }\n",
array[0], array[1], array[2], array[3]);
return 0;
}

.... would be similar in spirit to your original, but without the
distractions of pointers-to-pointers and so on.

--
Eric Sosman
(E-Mail Removed)lid
 
Reply With Quote
 
Ersek, Laszlo
Guest
Posts: n/a
 
      06-22-2010
On Tue, 22 Jun 2010, Eric Sosman wrote:

> array[index(1)] = array[index(2)] = array[index(3)] = 7;


Great, thanks!
lacos
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
function argument evaluation order and asserts and macros jacek.dziedzic@gmail.com C++ 4 09-24-2008 02:28 PM
expression and evaluation order and precedence rules silpau@gmail.com C Programming 26 06-15-2007 03:53 PM
[EVALUATION] - E03 - jamLang Evaluation Case Applied to Python Ilias Lazaridis Python 2 04-24-2005 05:29 PM
[EVALUATION] - E04 - jamPersist Evaluation Case Applied to Ruby Ilias Lazaridis Ruby 18 04-09-2005 04:45 PM
[EVALUATION] - E03 - jamLang Evaluation Case Applied to Ruby Ilias Lazaridis Ruby 74 04-04-2005 05:29 PM



Advertisments