C
Christian Bau
Tim Rentsch said:I believe that whether or not the compiler can deduce that no function
outside the single-translation-unit program is called is irrelevant.
First, 6.2.7 p1 doesn't say translation units in the same executable;
it just says translation units. Second, there are lots of ways a
structure value might be transmitted between different executables,
eg,
- writing bytes out to a file and another executable reading
them in;
- storing a value in shared memory;
- transmitting bytes over a pipe or a socket;
- just leaving a value in memory somewhere and expecting the
next program to pick it up;
- for a more subtle example - the value of an 'offsetof'
macro call might be stored by one executable and used
by another.
The C standard makes (some) guarantees about program execution, but it
seems silly to think it makes guarantees *only* about program
execution. There also are guarantees about what representations are
used in (some) data types. I think most people reading sections
6.2.5, 6.2.6, 6.2.7 and 6.3 would conclude that guarantees are made
about the representations of compatible types (of structs) in
different translation units, regardless of whether they were ever
bound into a single executable. In response to that, do you have
anything to offer other than just an assertion to the contrary?
Saying "... it is clearly allowed ..." without giving any supporting
statements isn't very convincing.
The C Standard gives a guarantee that under certain circumstances
modifying an object through a pointer to some struct modifies another
object in a defined way. Example:
typedef struct { int x; double y; char z; } s1;
typedef struct { int a; double b; short c; } s2;
typedef union { s1 x; s2 y; } u;
int main (void) {
s1 x;
((s2 *) &x) -> b = 3.7;
return 0;
}
The assignment is guaranteed to set x.y to 3.7. How the compiler does
this is none of anyones business. A simple strategy to achieve this is
for the compiler to use the same layout for all initial sequences of all
structs. That means the offset of any one struct member depends only of
the type of that member and all preceeding members, but not on the type
of any following members.
In my tiny example, it is clear that the compiler can achieve what is
guaranteed by the standard without using the same layout for s1 and s2.
All it needs to do is replace the left hand side of the assignment ((s2
*) &x)->b with x.y. That will achieve exactly what is guaranteed by the
C Standard. Yes, the simplest implementation will use the same offsetof
for s1.y and s2.b, but _that_ is not guaranteed by the C Standard.
So the situation is: The C Standard guarantees X. A simple method to
achieve this in an implementation is to do Y. A compiler would in fact
have to work hard to achieve X without doing Y. This does _not_
guarantee Y in any way, it guarantees X.
If the C Standard had wished to guarantee same layout for structures, it
would have been easy to add this.