On 02/09/16 18:49, Jerry Stuckle wrote:
> On 9/2/2016 11:59 AM, David Brown wrote:
>> On 02/09/16 14:50, Jerry Stuckle wrote:
>>> On 9/2/2016 3:35 AM, David Brown wrote:
>>>> On 02/09/16 03:02, Jerry Stuckle wrote:
<snip>
>>>> Secondly, as long as we are talking about memory that can only be seen
>>>> from within the program (while following the rules of C), memory layout
>>>> is nothing more than an effect of execution. The way a struct is laid
>>>> out is not observable behaviour in itself, and thus the compiler is free
>>>> to change it.
>>>>
>>>
>>> The struct layout is observable behavior, and cannot be changed. 9.2.13
>>> says so.
>>
>> No, 9.2.13 says nothing about observable behaviour. Read it again, and
>> see if you spot that phrase. And in the definition of observable
>> behaviour (section 1.9.8), no mention is made of struct layout or memory
>> (except in regard to volatile accesses).
>>
>> You are simply wrong here. You are making things up that are not in the
>> standards.
>>
>
> No, you are making up things which are not what the standard says. No,
> section 1.9.8 doesn't say anything about struct layout. That is not its
> purpose.
>
I did not say that 1.9.8 discussed the layout of structs - I said it did
/not/ cover struct layout.
> And 1.9.1 refers to the remainder of section 1.9, not the entire
> standard. Plus, 1.9 refers to program execution - not memory layout.
> Layout is not behavior.
1.9.1 refers to the observable behaviour, which is defined "below" in
1.9.8. Section 1.9.8 refers to the entire rest of the standard.
And memory layout is behaviour.
>
> 1.9.1 is for things like the following:
>
> a = 2;
> b = 3;
> c = 2;
>
> Can be reordered to
>
> a = c = 2;
> b = 3;
>
> Of course it's more than that. But to stay in line with what you can
> understand, I'm keeping it simple.
It covers /vastly/ more than that. It is the basis for the concept of
an "optimising compiler".
>
>>>
>>>> It is /not/ free to change struct layout when that data is passed to
>>>> external functions, written to files, or has volatile behaviour - those
>>>> are observable effects. But if the data stays within the program as
>>>> known to the compiler, the compiler is free to do as it wants.
>>>>
>>>
>>> Sorry, you are once again wrong. The compiler doesn't know what a
>>> function does. You are really grasping at straws now, David.
>>
>> If the compiler does not know what a function does (such as for external
>> functions), then it must assume the worst - it must assume it has
>> volatile accesses to all globally visible data, for example, and thus
>> any such data must follow the rules for struct layout. But it can
>> assume that the external function has defined behaviour - and thus
>> cannot read local data or file static data that has not escaped in some
>> way, and it can re-arrange such data as it likes.
>>
>
> And how is the compiler to know that? Does it predict the future?
>
> struct mystruc {
> int a, b;
> };
>
> func f() }
> struct mystruct ms;
> ms.a = 1; // The structure has been defined
> ms.b = 2;
> write(ms); // NOW the compiler knows that there is a call
> }
>
> It is a one-pass compiler. There is no way for it to know when
> assigning ms.a that there is going to be a call to another function.
>
That was perhaps true in the days when compilers read programs on
punched cards. But these days, compilers are smarter than that. Before
the compiler generates anything for "ms.a", it has already parsed all
the rest of the file - and perhaps all the other files in the program.
Perhaps you use a one-pass compiler, with all its limitations. I don't
know how many passes modern gcc or clang have, but according to a quick
google gcc 4.6.2 had 207 unique passes.
>
>> And if the compiler knows the definition of the function, then it will
>> know which re-arrangements and optimisations are safe. With
>> whole-program or link-time optimisation, the compiler may even know the
>> definitions of every function in the program.
>>
>
> Not before the structure has been defined.
The compiler collects all the information about the program, data,
structures, functions, etc., before it starts organising the data or
generating the code. That's the point of whole-program optimisation.
>
>>>
>>> Just admit you are wrong and move on. Or explain why 9.2.13 exists,
>>> when according to you, it is meaningless.
>>>
>>
>> No, only you have claimed it is meaningless. I am quite happy with its
>> meaning.
>>
>
> No, you said the compiler is free to reorder the memory. That is in
> direct conflict with 9.2.13. So it is you who declare it meaningless.
Yes, the compiler is free to re-order anything it likes - code,
functions, memory, structs, whatever - as long as the observable
behaviour is unchanged.
>
> You are just digging yourself a deeper and deeper hole,
>
You simply don't understand much about how compilers work. That's okay,
you don't have to know how they work in order to use them. But you do
look silly by continuing to flaunt your ignorance.
But keep going, if you like - it is somewhat entertaining. The idea
that a modern C compiler is one-pass and generates the code for one line
of source before reading the next line gave me a bit of a chuckle.