Evaluation order of assignment.
Wayne A. Throop
throopw at xyzzy.UUCP
Sat Aug 20 04:19:25 AEST 1988
> schmidt at bonnie.ics.uci.edu (Douglas C. Schmidt)
> Is the following always guaranteed to produce the "intended" result:
>
> struct list {
> int item;
> struct list *next;
> };
>
> struct list foo()
> {
> struct list head;
>
> return(head->next = head = (struct list *) malloc(sizeof(struct list)));
> }
>
> My intention is to create a dummy node in a circularly-linked list,
> and assign the dummy node's next field to point to the head of
> the list. Since assignment associates from right-to-left this
> will alway work, right (cryptic style notwithstanding !! ;-)).
This intent is very hard to deduce from the code, since the code is, in
fact, illegal C. To whit, lint has this to say about the return
statement:
x1.c
==============
(10) operands of = have incompatible types
(10) operands of RETURN have incompatible types
(10) warning: head evaluation order undefined
warning: illegal combination of pointer and integer:
(10) operator =
warning: struct/union or struct/union pointer required
(10)
Further, another tool found this extra problem:
./x1.c 10 incorrect expression type
The expression is: head->next
Its type is: struct list
The expected type is: a pointer type
So, translating "foo" to be what was probably meant:
struct list *foo(){
struct list *head;
return(head->next = head =
(struct list *) malloc(sizeof(struct list)));
}
And running THAT through lint, we find:
(9) warning: head evaluation order undefined
SO, the final result we come up with is:
"No, that code will not portably do what you intend."
The reason for this is that a side-effect takes place to the variable
"head" within the expression, and the sequencing of side effects are not
guaranteed in C. Thus, the head in "head->next" might be pointing to
the newly allocated node, or to whatever the garbage it contained was
pointing to.
So, the return would have to be coded like so, introducing a sequence
point to guarantee order of evaluation:
return(head = (struct list *) malloc(sizeof(struct list)),
head->next = head );
> thanks,
You're welcome.
--
Standards should be discovered, not decreed.
--- Padlipsky
--
Wayne Throop <the-known-world>!mcnc!rti!xyzzy!throopw
More information about the Comp.lang.c
mailing list