Liste des Groupes | Revenir à cl c |
On 08/07/2024 19:39, BGB wrote:On 7/7/2024 11:28 PM, James Kuyper wrote:On 7/7/24 20:02, Kaz Kylheku wrote:
...I see no point in having implicit pointers, but I don't believe
that they are prohibited.
They mostly exist in a "sort of simpler to implement the compiler
this way" sense.
In the implicit pointer case, the compiler just treats it as-if it
were an explicit pointer. In this case, both are basically treated
as being roughly equivalent at the IR levels.
And, most of the code-generation stage doesn't need separate
handling for arrays and pointers, but can use combined
"ArrayOrPointer" handling or similar.
It had all seemed "obvious enough".
Similar reasoning for passing structs by-reference in the ABI:
Pass by reference is easy to implement;
In place copying and decomposing into registers, kinda bad.
Though, this one seems to be a common point of divergence between
"SysV" and "Microsoft" ABIs. Sometimes a target will have an ABI
defined, and the MS version was almost the same, just typically
differing in that it passes structs by reference and provides a
spill space for register arguments.
I don't think it is helpful that you keep mixing /logical/ terms with
/implementation/ terms.
In C, there is no "pass by reference" or "return by reference". It
is all done by value. Even when you use pointer arguments or return
types, you are passing or returning pointer values. C programmers
use pointers to get the effect of passing by reference, but in C you
use pointers to be explicit about references.
Structs in C are passed by value, and returned by value. Not by
reference.
The C standards don't say how passing structs around by value is to
be implemented - that is hidden from the programmer. Usually ABI's
(which are also hidden from the programmer) specify the
implementation details, but some ABI's are weak in that area.
Generally, structs up to a certain size or complexity are passed in
registers while bigger or more advanced types are passed via
addresses (pointing to stack areas) in registers or the stack, just
like any other bigger types. This is not "pass by reference" as far
as the C programming is concerned - but you could well call it that
at the assembly level. Where the line between "passing in registers"
and "passing via addresses to space on the stack" is drawn, is
entirely up to the compiler implementation and any ABI requirements.
Some simpler compilers will pass all structs via addresses, no matter
how simple they are, while others will aim to use registers whenever
possible.
So if you have these structs and declarations :
struct small { uint16_t a; uint16_t b; };
struct big { uint32_t xs[10]; };
struct small foos(struct small y);
struct big foob(struct big y);
Then compilers will typically implement "x = foos(y)" as though it
were:
extern uint32_t foos(uint32_t ab);
uint32_t _1 = foos(y.a << 16) | (y.b);
struct small x = { _1 >> 16, _1 & 0xffff };
And they will typically implement "x = foosb(y)" as though it were:
extern void foob(struct big * ret, const struct big * xs);
struct big x;
foob(&x, &y);
>
This is not, as you wrote somewhere, something peculiar to MSVC - it
is the technique used by virtually every C compiler, except perhaps
for outdated brain-dead 8-bit microcontrollers that have difficulty
handling data on a stack.
And it is not really "pass by reference" or "implicit pointers", it
is just passing addresses around behind the scenes in the
implementation.
Les messages affichés proviennent d'usenet.