[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Lies in education [was Re: The "loop and a half"]

On 11/10/2017 19:30, Chris Angelico wrote:
> On Thu, Oct 12, 2017 at 5:22 AM, Grant Edwards

>> The easiest way to make stuff like that readable is to unroll them
>> into a sequence of typedefs.  But, a lot of people never really
>> learn how to do that...
> The most complexity you'll usually see is a function that
> accepts/returns a pointer, and those generally should be typedef'd.
> But even if not, they're still not anything like as bad as the
> mythical examples that get touted as "why C is bad" or "why variable
> declarations are bad" or "why type declarations are bad".

IME typedefs can make things worse, especially if used even for basic 
types. Then you spend your time tracing back typedefs to see what they 
mean (was it a char, or struct or what?).

C can combine the abstruseness of its type declarations, overuse of 
macros, and overuse of #if/ifdef blocks to render a lot of code a 
complete nightmare to try and understand. Or debug. Or maintain. Or 
port. Or implement (if testing a compiler).

I've looked at some of my generated C code, and here's one common 
example, not a complex type:

     tokenrec * (*)[]

But I couldn't figure that out from the top of my head. Bear in mind 
this was in a parameter list that can change the meaning of []. I looked 
at the original source and that type is written like this:

     ref [] ref tokenrec

'ref' means 'pointer to', and it can also be written like this:

     pointer [] pointer tokenrec

In English, 'pointer to array of pointer to tokenrec'. See how the 
source language corresponds almost exactly to the English, and both are 
written left to right. Now go back and look at the C version - where do 
you even start? Are those parentheses significant? (I've no idea.)

The most complex of /my/ types to appear in generated C is probably 
this, used as a cast in this assignment:

      pcptr = (*(int64 * (**) (void))pcptr)();

(Original source is this:

     pcptr := ref ref function=>ref int64(pcptr)^^()

In English, the cast is 'pointer to pointer to function returning 
pointer to int64'.

The line includes two dereferences (^^) which /I think/ account for two 
of the "*" in the C version. Which * are dereferences, and which are 
part of the type, or indeed whether only one * is the dereference, I 
have absolutely no idea. Great language...)