[TUHS] Minimum Array Sizes in 16 bit C (was Maximum)

Luther Johnson luther.johnson at makerlisp.com
Sun Sep 29 08:45:26 AEST 2024


G. Branden,

I get it. From your and Doug's responses, even O(n) baked-in costs can
be a problem.

On 09/28/2024 03:08 PM, Luther Johnson wrote:
> "Classic C", K&R + void function return type, enumerations, and
> structure passing/return, maybe a couple other things (some bug
> fixes/stricter rules on use of members in structs and unions), has
> this, I use a compiler from 1983 that lines up with an AT&T System V
> document detailing updates to the language.
>
> I view these kinds of changes as incremental usability and reliability
> fixes, well within the spirit and style, but just closing loopholes or
> filling in gaps of things that ought to work together, and could,
> without too much effort. But I agree, structures as full-fledged
> citizens came late to K & R / Classic C.
>
> On 09/28/2024 11:46 AM, G. Branden Robinson wrote:
>> Hi Luther,
>>
>> At 2024-09-28T10:47:44-0700, Luther Johnson wrote:
>>> I don't know that structure copying breaks any complexity or bounds on
>>> execution time rules. Many compilers may be different, but in the
>>> generated code I've seen, when you pass in a structure to a function,
>>> the receiving function copies it to the stack. In the portable C
>>> compiler, when you return  a structure as a result, it is first copied
>>> to a static area, a pointer to that area is returned, then the caller
>>> copies that out to wherever it's meant to go, either a variable that's
>>> being assigned (which could be on the stack or elsewhere), or to a
>>> place on the stack that was reserved for it because that result will
>>> now be an argument to another function to be called. So there's some
>>> copying, but that's proportional to the size of the structure, it's
>>> linear, and there's no dynamic memory allocation going on.
>> I have no problem with this presentation, but recall the principle--the
>> tenet--that Doug was upholding:
>>
>>>> At 2024-09-28T09:34:14-0400, Douglas McIlroy wrote:
>>>>> This complaint overlooks one tenet of C: every operation in what
>>>>> you call "language runtime" takes O(1) time. Dynamic memory
>>>>> allocation is not such an operation.
>> Even without dynamic memory allocation, if you did something linear,
>> something O(n), it was a lose and a violation of the tenet.
>>
>> I can easily see the appeal of a language whose every operation really
>> is O(1).  Once upon a time, a university course, or equivalent
>> experience, in assembly language (on a CLEAN instruction set, not x86)
>> is what taught you the virtues and drawbacks of thinking about and
>> implementing things that way.  But my view is that C hasn't been one of
>> those languages for a very long time, since before its initial ANSI
>> standardization at the latest.
>>
>> At 2024-09-28T10:52:16-0700, Luther Johnson wrote:
>>> In the compilers I'm talking about, you pass a structure by passing a
>>> pointer to it - but the receiving function knows the argument is a
>>> structure, and not a pointer to a structure, so it knows it needs to
>>> use the pointer to copy to its own local version.
>> It's my understanding that the ability to work with structs as
>> first-class citizens in function calls, as parameters _or_ return types,
>> was something fairly late to stabilize in C compilers. Second-hand, I
>> gather that pre-standard C as told by K&R explicitly did _not_
>> countenance this.  So a lot of early C code, including that in
>> libraries, indirected nearly all struct access, even when read-only,
>> through pointers.
>>
>> This is often a win, but not always.  A few minutes ago I shot off my
>> mouth to this list about how much better the standard library design
>> could have been if the return of structs by value had been supported
>> much earlier.
>>
>> Our industry has, it seemss, been slow to appreciate the distinction
>> between what C++ eventually came to explicitly call "copy" semantics and
>> "move" semantics.  Rust's paradigmatic dedication to the concept of data
>> "ownership" at last seems to be popularizing the practice of thinking
>> about these things.  (For my part, I will forever hurl calumnies at
>> computer architects who refer to copy operations as "MOV" or similar.
>> If the operation doesn't destroy the source, it's not a move--I don't
>> care how many thousands of pages of manuals Intel writes saying
>> otherwise.  Even the RISC-V specs screw this up, I assume in a
>> deliberate but embarrassing attempt to win mindshare among x86
>> programmers who cling to this myth as they do so many others.)
>>
>> For a moment I considered giving credit to a virtuous few '80s C
>> programmers who recognized that there was indeed no need to copy a
>> struct upon passing it to a function if you knew the callee wasn't going
>> to modify that struct...but we had a way of saying this, "const", and
>> library writers of that era were infamously indifferent to using "const"
>> in their APIs where it would have done good.  So, no, no credit.
>>
>> Here's a paragraph from a 1987 text I wish I'd read back then, or at any
>> time before being exposed to C.
>>
>> "[Language] does not define how parameter passing is implemented.  A
>> program is erroneous if it depends on a specific implementation method.
>> The two obvious implementations are by copy and by reference. With an
>> implementation that copies parameters, an `out` or `in out` actual
>> parameter will not be updated until (normal) return from the subprogram.
>> Therefore if the subprogram propagates an exception, the actual
>> parameter will be unchanged.  This is clearly not the case when a
>> reference implementation is used.  The difficulty with this vagueness in
>> the definition of [language] is that it is quite awkward to be sure that
>> a program is independent of the implementation method.  (You might
>> wonder why the language does not define the implementation method.  The
>> reason is that the copy mechanism is very inefficient with large
>> parameters, whereas the reference mechanism is prohibitively expensive
>> on distributed systems.)"[1]
>>
>> I admire the frankness.  It points the way forward to reasoned
>> discussion of engineering tradeoffs, as opposed to programming language
>> boosterism.  (By contrast, the trashing of boosters and their rhetoric
>> is an obvious service to humanity.  See?  I'm charitable!)
>>
>> I concealed the name of the programming language because people have a
>> tendency to unfairly disregard and denigrate it in spite of (or because
>> of?) its many excellent properties and suitability for robust and
>> reliable systems, in contrast to slovenly prototypes that minimize
>> launch costs and impose negative externalities on users (and on anyone
>> unlucky enough to be stuck supporting them).  But then again cowboy
>> programmers and their managers likely don't read my drivel anyway.
>> They're busy chasing AI money before the bubble bursts.
>>
>> Anyway--the language is Ada.
>>
>> Regards,
>> Branden
>>
>> [1] Watt, Wichmann, Findlay.  _Ada Language and Methodology_.
>>      Prentice-Hall, 1987, p. 395.
>



More information about the TUHS mailing list