Path: ...!news.mixmin.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: David Brown Newsgroups: comp.lang.c Subject: =?UTF-8?Q?Re=3a_technology_discussion_=e2=86=92_does_the_world_need?= =?UTF-8?B?IGEgIm5ldyIgQyA/?= Date: Tue, 9 Jul 2024 18:31:43 +0200 Organization: A noiseless patient Spider Lines: 92 Message-ID: References: <871q48w98e.fsf@nosuchdomain.example.com> <87wmlzvfqp.fsf@nosuchdomain.example.com> <87h6d2uox5.fsf@nosuchdomain.example.com> <20240707164747.258@kylheku.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Injection-Date: Tue, 09 Jul 2024 18:31:43 +0200 (CEST) Injection-Info: dont-email.me; posting-host="b5f81ffa340fccea092912f722a4136c"; logging-data="1519463"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+h8/eNP/ockGnhGSTu1XEyiDVXUuOCME0=" User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.11.0 Cancel-Lock: sha1:xzaCbs0aVADvvQraH9f1SF/q+EQ= Content-Language: en-GB In-Reply-To: Bytes: 5115 On 09/07/2024 16:54, bart wrote: > On 09/07/2024 15:31, David Brown wrote: >> On 08/07/2024 19:39, BGB wrote: > >>> 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. > > Arrays are passed by reference: > >   void F(int a[20]) {} > >   int main(void) { >     int x[20]; >     F(x); >   } > > Although the type of 'a' inside 'F' will be int* rather than int(*)[20]. Arrays are not passed by reference in C. When you use the array in most expression contexts, including as an argument to a function call, the array expression is converted to a pointer to its first element, and that pointer is passed by value. That's why the array type information is lost in the call, and you get a pointer in the function - /not/ a reference to an array. > >> 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); > > From what I've seen, structs that are not small enough to be passed in > registers, are copied to a temporary, and the address of that temporary > is passed. That will depend on the details of the compiler, optimisation, and what happens to the array after the call. But yes, that is certainly something that is done. > > This seems to be the case even when the struct param is marked 'const'. "const" in C is not strong enough to guarantee that things will not be changed in this context. If you have a pointer to non-const data, convert it to a pointer to const, and then later convert it back to a pointer to non-const, you can use that to change the data. Thus using a pointer to const does not let the compiler be sure that the data cannot be changed by the function - so if the struct/array is used again later, and its value must be preserved, the compiler needs to make a copy. (I'd like it if there were a way to have such guarantees, but C is what C is.) > > (My compiler won't create a copy when the parameter is 'const'. I > assumed that was how gcc did it; I was wrong.) Your compiler is wrong. But if you only give it code where the const pointer is never converted to a non-const pointer, you'll be safe. > > This is for Win64 ABI, however an ABI will only say they are passed by > reference; it will not stipulate making a copy. That is up to the > language implementation. >