================================================================ C9X Revision Proposal ===================== Title: C and C++ structure assignment compatibility Author: Tom MacDonald Author Affiliation: Cray Research, and SGI company Postal Address: Cray Research Park 655F Lone Oak Drive Eagan, MN 55121 USA E-mail Address: tam@cray.com Document Number: WG14/N647 (X3J11/97-010) Telephone Number: +1-612-683-5818 Fax Number: +1-612-683-5307 Sponsor: X3J11 Date: 1997-01-07 Proposal Category: __ Editorial change/non-normative contribution __ Correction XX New feature __ Addition to obsolescent feature list __ Addition to Future Directions __ Other (please specify) Change of current behavior Area of Standard Affected: __ Environment XX Language __ Preprocessor __ Library __ Macro/typedef/tag name __ Function __ Header __ Other (please specify) ______________________________ Prior Art: C++ Target Audience: all C programmers (C++ compatibility) Related Documents (if any): NONE Proposal Attached: __ Yes XX No, but what's your interest? A proposal will be submitted if WG14/X3J11 feel this is an issue. Abstract: Make C structure copies compatible with C++ ======================= Cover sheet ends here ============== Problem Statement: Recently I became aware of an incompatibility between C and C++ that WG14/X3J11 should consider while defining C9X, the next C Standard. Consider the following example: struct S_Pair; typedef struct Object { struct S_Pair *addr; int tag; } Object; struct S_Pair { Object car; Object cdr; }; Object x; void copy_it(void) { x = x.addr->cdr; } The C++ rules permit the following implementation of the structure assignment inside the function copy_it. x.addr = x.addr -> cdr.addr; x.tag = x.addr -> cdr.tag; The C rules are more strict as indicated in 6.3.16.1, the first paragraph under Semantics says: In simple assignment(=), the value of the right operand is converted to the type of the assignment expression and replaces the value stored in the object designated by the left operand. Note that the value is spoken of as a whole. There appears to be nothing that allows the identity of the right operand to change in the middle of the assignment, which is the effect what the C++ rules permit. The second paragraph under Semantics forbids partial overlap. This allows a more efficient implementation of a structure assignment (between lvalues) as memcpy(&left_operand, &right_operand) or an inline equivalent, rather than as memmove(&left_operand, &right_operand) which would include the extra work needed to accommodate the possibility of partial overlap (such as copying through a temporary object, or deciding whether to copy bytes from the beginning or from the end). Note that in either case, the addresses of the two operands are computed before the copying begins. The following implementation produces the expected C behavior. { Object * tmp = &(x.addr->cdr); x.addr = tmp->data; x.tag = tmp->tag; } The question being submitted to this committee is whether C should change to become compatible with C++ in this area? Things to consider: - The C++ rules introduce a QUIET CHANGE into C9X - The example in question seems like an unusual case - Adopting the C++ rules allows an implementation that supports both C and C++ in the same compiler to avoid special casing this rarity. Finally, if the committee decides to adopt the C++ rules, a proposal is needed that shows the wording changes needed.