JTC1/SC22/WG14
N647
================================================================
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.