Author Topic: C word  (Read 34338 times)

0 Members and 1 Guest are viewing this topic.

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4316
  • Country: us
Re: C word
« Reply #100 on: September 25, 2019, 01:09:07 am »
Quote
The 'Size' attribute (Ada has attributes, as some other languages do)

yeah, I looked up "ada attributes" and got really confused, since they seem to merge what I'd normally conside constant definitions, attributes, and methods.

Code: [Select]
for Byte_t'Size use 8;   -- clearly like a C attribute; makes the type use 8 bits.
val := Variable'Size;    -- behaves more like sizeof (same attribute, different function!)
val := Variable'Last;    -- sort of like MAXINT, if variable is an int (sorta nice, actually)
str := Variable'image;   -- definitely method-like (doesn't work for user-defined types?)

Sigh.  And I guess this is the sort of stuff that never actually shows up in most "beginning" tutorials.  One of those things that you either need to read a lot of code, write a lot of code that is ruthlessly peer-reviewed, or work somewhere where "common usage" is well-defined (which is a combination if "read a lot"+"write a lot", really.)
« Last Edit: September 25, 2019, 01:10:50 am by westfw »
 

Offline golden_labels

  • Super Contributor
  • ***
  • Posts: 1371
  • Country: pl
Re: C word
« Reply #101 on: September 25, 2019, 01:31:39 am »
You're the confused one: you don't use a hosted environment (with the standard library available) for microcontrollers or kernels and such anyway.  The standard C library is only really useful for portable applications.
C has little use outside kernels, microcontrollers, implementing other programming environments and writing some snippets to optimize fragments that do not perform well enough. Sure, I know there are many people who still try, but that doesn’t mean it has any sense. C is not suitable for that purpose in 2019.

In practice, the C implementations have already split the standard library, as the C compiler provides some of the functions instead of the C library.  (…)
But that is not required by the language. Those are imlementation details.

Are you indirectly saying that C isn't suited to the following use cases: (…)
I have quite directly said “It’s still PDP-11, relaxed a bit to allow different platforms.

Which bits of the PDP-11 is C boat-anchored onto?
  • SISD architecture: unable to represent SIMD or manycores.
  • Flat and linear memory model.(1)
  • No way to control timing and nearly no control over ordering of operations.
  • Poor support for multithreaded programs, multiprocessor machines and interrupts/signals.
____
(1) C doesn’t prohibit different models and explicitly defines pointers in a way that makes them possible, but provides no actual means of ever using that directly.
People imagine AI as T1000. What we got so far is glorified T9.
 

Offline legacy

  • Super Contributor
  • ***
  • !
  • Posts: 4415
  • Country: ch
Re: C word
« Reply #102 on: September 25, 2019, 06:13:38 am »
    Poor support for multithreaded programs, multiprocessor machines and interrupts/signals.[/li][/list]

    Yup. C-threads cannot be a library, hence programming in C on machines like Parallela is ... well, if it's hobby, there are better way to obtain headache  :D
     

    Offline FreddieChopin

    • Regular Contributor
    • *
    • !
    • Posts: 102
    • Country: ua
    Re: C word
    « Reply #103 on: September 25, 2019, 06:31:27 am »
    You're the confused one: you don't use a hosted environment (with the standard library available) for microcontrollers or kernels and such anyway.  The standard C library is only really useful for portable applications.
    C has little use outside kernels, microcontrollers, implementing other programming environments and writing some snippets to optimize fragments that do not perform well enough. Sure, I know there are many people who still try, but that doesn’t mean it has any sense. C is not suitable for that purpose in 2019.

    Gr8 b8 m8. C is like catholicism or SQL - has its flaws but gets the job done. It existed before us, it exists now and it'll be fine after we're long gone. I can assure you that in 30 years from now Rust, JS or Go may be gone or at least change so much that current code won't even compile.
     

    Offline legacy

    • Super Contributor
    • ***
    • !
    • Posts: 4415
    • Country: ch
    Re: C word
    « Reply #104 on: September 25, 2019, 06:40:35 am »
    No way to control timing and nearly no control over ordering of operations.

    On superscalar machines like PowerPC, this is usually managed with assembly-inline instructions { eieio, sync, isync, ... }. But you need to manually create barriers here and there, and in the end, the resulting code looks like you have spent your precious time at making things ugly and not portable.

    But it's not so negative, since C-guys call it "black voodoo magic", with neither a precise science nor a code style. It's hipster and pop, but they love because everyone can express their own style.

    What is your proposal for supporting this directly by the language?  :D
     

    Offline magic

    • Super Contributor
    • ***
    • Posts: 7246
    • Country: pl
    Re: C word
    « Reply #105 on: September 25, 2019, 08:34:14 am »
    The whole point of C is that it is small, it is and it works.

    I can't imagine who in his right mind would be interested in "evolving" C. If you need a bigger language which routinely receives every new feature invented in the industry, such a language already exists and it will even compile 99% of your existing C codebase with minor modification. For essentially the same language as C but with semantics more suitable for SIMD, see OpenCL

    Shared memory multithreading is indeed one area where C kinda sucks and could use improvement without turning it into something it was never meant to be. And it is slowly receiving improvements in that.

    Pushing POSIX into C doesn't make sense, there is already a standard for POSIX and any half-decent OS today supports POSIX. If you have an issue with one particular vendor refusing to support POSIX, talk to your vendor :P
    Or use a 3rd party implementation like the Cygwin libraries.
     

    Offline hamster_nz

    • Super Contributor
    • ***
    • Posts: 2812
    • Country: nz
    Re: C word
    « Reply #106 on: September 25, 2019, 09:06:06 am »
    Shared memory multithreading is indeed one area where C kinda sucks and could use improvement without turning it into something it was never meant to be. And it is slowly receiving improvements in that.

    I would rephrase that... as "Shared memory / Multithreading is indeed one area in C where you really need to know what you are doing, and do good design work up front before you start coding."

    However, if you want things to be completely safe, where all resources are properly fenced, the garbage is collected regularly, and everything is properly maintained by the system you will pay for it by needing lots of CPU and other overheads, and reduced performance.

    A few months ago I wrote a REST API & server in less than 300 lines of Python, using WSGIserver - "WSGIserver is a high-speed, production ready, thread pooled, generic WSGI server with SSL support" - https://pypi.org/project/WSGIserver/.

    It took 0.7s to process a simple transaction, so could only support 1.4 transactions per second, and was in a 600MB+ Docker container.

    Now that the API design has settled down I re-wrote in C with the same external interfaces (HTTPS, SQLite3, a SMB file share), It took 3,000 lines of C, but now can handle 120 transactions per second.  The new Docker container is a little over 100MB.

    I guess I could have just stood up 25 quad-core instances in Azure to achieve the same scaling without any extra coding effort...
    Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
     
    The following users thanked this post: SiliconWizard

    Offline Nominal Animal

    • Super Contributor
    • ***
    • Posts: 6967
    • Country: fi
      • My home page and email address
    Re: C word
    « Reply #107 on: September 25, 2019, 12:16:15 pm »
    What do you mean by a hosted environment?
    I'm using the term as defined by the C standard.  See e.g. C99 (PDF).

    Basically, when you write code to run on a machine with an operating system that provides an implementation of the standard C library, you are using a hosted environment.  When you write code to run on bare metal, without the standard C library, you are using a freestanding environment.

    C has little use outside kernels, microcontrollers, implementing other programming environments and writing some snippets to optimize fragments that do not perform well enough. Sure, I know there are many people who still try, but that doesn’t mean it has any sense. C is not suitable for that purpose in 2019.
    Your opinion does not match reality.

    Most libraries are written in C, because that way the set of dependencies is minimized.  Some do use C++, but that poses several difficult to solve issues, because of the memory management differences, exception propagation, and the run-time dependency on the particular version of C++ libraries.

    As a practical example, all libraries you use to read/write image files, XML, access USB devices, et cetera, are most likely written in C.  (All the portable ones are written in C, but there are of course libraries that only work on a single hardware architecture on a single version of a specific OS.)

    One of my suggestions for creating portable GUI applications is to use Python 3 and Qt for the user interface (which does not contain any features that need protecting, because any such features are trivially replicated even without the source code), and C for the underlying computation and access.  This is the same model as used in e.g. NumPy and SciPy libraries/library collections.

    In practice, the C implementations have already split the standard library, as the C compiler provides some of the functions instead of the C library.  (…)
    But that is not required by the language. Those are imlementation details.
    That is exactly the simplistic view that kills the development of a programming language.

    You see, programming languages do not evolve by the standard; the standard just codifies existing portable practices.  If the standard diverges from existing practices, it becomes unreliable; if the standard ignores changes in practices, it becomes stagnant.  Programmers read the standard to see what to expect from compilers, and compiler developers read the standard to understand what features the compiler should support.  The features I listed above are already available in all POSIXy operating systems' standard C libraries (Linux, Mac, BSDs), and as optional libraries in Windows and historical non-POSIXy Unixes.
    Even including just getline() into the standard C library would solve an entire class of problems (line length limitations) for both new programmers and library implementors.

    Currently, the best portable standard set is C99 with POSIX.1-2008.  The only major OS that does not support it natively by their C library (POSIX.1 is not a separate library, but a set of additional interfaces and functions provided by the standard C libraries the OS provides), is Windows; there, you need to use shims and whatnot.  It does not matter much, because only trivial code that runs on Windows runs on other OSes.

    It mostly affects those learning C, because if they use Windows, they have a hard time separating what is C, and what are Microsoft extensions/weirdnesses.  (For example, fwide() does not work on Windows; you need to use a Microsoft-ism to do the same thing.  Why didn't MS just include their extension weirdness inside fwide() and make it work, is a mystery.)

    So, when you train C programmers, you either use an OS other than Windows, or you spend an inordinate time explaining to them why the documentation they follow (from MS) is wrong, and why they need to go through all sorts of odd hoops to get their code working properly on Windows.  Or, you let them become Microsoft C programmers, who cannot write portable code.

    The whole point of C is that it is small, it is and it works.
    You are conflating the C standard library (hosted environment), and the C language itself (as used in a freestanding environment).

    The C language itself is small, but lacks support for important features (the status flags register in particular).

    What I am suggesting, is divided into two completely separate paths.  One is to include the POSIX.1 features that are already supported by all OSes in the standard C library proper, although in Windows via different interfaces.  This excludes things like signals, but includes things like getline().  Exactly what things to include should obviously be discussed; but since C99, has not at all.  The other is to add features to the language itself.  Unlike changes to the C library, changing the language syntax itself creates a new language.  So, adding things like unordered loops or variable attributes, creates a new programming language, a C derivative.

    These two paths are not mutually exclusive.  Updating the C standard library would not affect existing C code, but would allow future C code to be both portable, and effective without additional dependencies.  (Existing de-facto standards like opendir()/readdir()/closedir() have fatal flaws; in particular, its depth is limited by the number of DIR* handles a process can have open at any moment, and it is very difficult to make it behave correctly when changes to the directory contents occur at the same time as the directory is scanned.  Having the C library implement glob() and nftw() allows OS-specific tricks to avoid both of these issues.  Instead of nftw(), one could also consider fts_open()/fts_read()/fts_children()/fts_set()/fts_close() from BSDs.)

    Adding features to the C standard library does not affect C freestanding environments at all (say, writing a kernel, or code for a microcontroller).  Because these features already exist in standard libraries (albeit with different function names and calling conventions in Windows), they would not "bloat" the standard C library either: this stuff already exists in them, I'd just want to standardize their interfaces, so that C code would be truly portable, and not need a mess of preprocessor directives to cater for the oddities in one.

    Adding features to the C language itself is a much longer-term proposition; we'd be talking about one or two decades instead of years for its adoption, due to the sheer amount of existing C code.  For me, it is more like an interesting research topic: what kind of language would match our uses of the existing hardware even better than C, while being easier to optimize, and not require any kind of runtime?
    « Last Edit: September 25, 2019, 12:30:12 pm by Nominal Animal »
     

    Offline magic

    • Super Contributor
    • ***
    • Posts: 7246
    • Country: pl
    Re: C word
    « Reply #108 on: September 25, 2019, 03:47:27 pm »
    Shared memory multithreading is indeed one area where C kinda sucks and could use improvement without turning it into something it was never meant to be. And it is slowly receiving improvements in that.

    I would rephrase that... as "Shared memory / Multithreading is indeed one area in C where you really need to know what you are doing, and do good design work up front before you start coding."

    However, if you want things to be completely safe, where all resources are properly fenced, the garbage is collected regularly, and everything is properly maintained by the system you will pay for it by needing lots of CPU and other overheads, and reduced performance.
    It's not just that, but also some standard library functions which aren't thread-safe for stupid reasons or lack of portable atomics and memory barriers until recently. And of course fanboys of Rust or ATS would want a word with you too ;)

     

    Online SiliconWizard

    • Super Contributor
    • ***
    • Posts: 15439
    • Country: fr
    Re: C word
    « Reply #109 on: September 25, 2019, 06:15:13 pm »
    Shared memory multithreading is indeed one area where C kinda sucks and could use improvement without turning it into something it was never meant to be. And it is slowly receiving improvements in that.

    I would rephrase that... as "Shared memory / Multithreading is indeed one area in C where you really need to know what you are doing, and do good design work up front before you start coding."

    However, if you want things to be completely safe, where all resources are properly fenced, the garbage is collected regularly, and everything is properly maintained by the system you will pay for it by needing lots of CPU and other overheads, and reduced performance.
    It's not just that, but also some standard library functions which aren't thread-safe for stupid reasons or lack of portable atomics and memory barriers until recently. And of course fanboys of Rust or ATS would want a word with you too ;)

    Do you mean that they wouldn't agree about the required overhead? That would just be stupid if so. Guarding shared resources requires overhead whatever you do.
    One way of circumventing this would be never to use shared resources (such as only passing messages), but that incurs other limitations and other forms of overhead. Nothing is free.
     

    Offline PlainName

    • Super Contributor
    • ***
    • Posts: 7314
    • Country: va
    Re: C word
    « Reply #110 on: September 25, 2019, 07:14:39 pm »
    Quote
    Basically, when you write code to run on a machine with an operating system that provides an implementation of the standard C library, you are using a hosted environment.  When you write code to run on bare metal, without the standard C library, you are using a freestanding environment.

    OK. Just that I have written code for bare metal that has the usual library functions supplied by the compiler vendor that would class it as hosted, so I'm not sure the differentiation in this discussion is useful.
     

    Offline Nominal Animal

    • Super Contributor
    • ***
    • Posts: 6967
    • Country: fi
      • My home page and email address
    Re: C word
    « Reply #111 on: September 25, 2019, 08:23:20 pm »
    Quote
    Basically, when you write code to run on a machine with an operating system that provides an implementation of the standard C library, you are using a hosted environment.  When you write code to run on bare metal, without the standard C library, you are using a freestanding environment.
    OK. Just that I have written code for bare metal that has the usual library functions supplied by the compiler vendor that would class it as hosted
    No, that is more properly called the HAL, hardware abstraction layer.  Usually, vendors also provide a subset of useful functions, especially things like snprintf(), but that does not make those environments hosted; just providing a subset of standard C libraries.

    This is strikingly similar to using C++ on microcontrollers: you are restricted to a subset, typically excluding exceptions and other features requiring a runtime, because there simply aren't enough resources to provide a standards-conformant C++ environment.

    I'm not sure the differentiation in this discussion is useful.
    It matters a lot, but not in the obvious sense.

    You see, because of lack of standardization, each microcontroller vendor (and environments like Arduino or PlatformIO) provides their own subset.  While this gives the vendors a lot of leeway, it makes it difficult to port C code between vendors.  They like it that way, just like Microsoft prefers that programmers who learned C on their platform, will find all other OSes odd or uncomfortable, due to the differences.  This is standard vendor lock-in practice.

    Because of the stuffing of the C standard committee, and opinions like golden_labels expressed (things being just "implementation details"), there is no way forward that helps developers (write portable code, and not locked-in to any specific vendor).  This affects both hosted and freestanding environments, but from the opposite ends of the same issue.

    If we added features to the standard C library, from POSIX.1 or BSD, making it a complete systems programming language, low-level libraries would be much easier to port across OSes, and in many cases more efficient than they currently are.

    At the same time, if we split the concept of "standard C library" into discoverable features, including features not useful in a hosted environment, we could unify the low-level interfaces used in C on top of bare metal.  No changes to the language are needed, as existing software uses the preprocessor to discover features (see e.g. Pre-Defined Compiler Macros); all we need is just agreement on the developer interfaces.

    All this is exactly what should be discussed by the C standard folks.  They have zero interest to, because they are only interested in how the standard affects the C compilers they provide.

    That said, I do believe that in the long run, we will need to replace C with something that occupies the same position in the software stack development hierarchy, but better utilizes current and future hardware.  I don't think Harvard architectures will be going anywhere soon, and memory segregation even within a process makes a lot of sense, so multiple address spaces and similar variable and expression attributes are needed.  (Currently, they use compiler-specific extensions, and even GCC is trying to grow real support for multiple address spaces.)

    It's not that C is "bad", it is just that the hardware has evolved so much there is now a clear niche, IMNSHO, for a language that fits that stratum better.
     

    Offline PlainName

    • Super Contributor
    • ***
    • Posts: 7314
    • Country: va
    Re: C word
    « Reply #112 on: September 25, 2019, 08:28:19 pm »
    OK. Thanks for the considered (and lengthy) explanation  :-+
     

    Online SiliconWizard

    • Super Contributor
    • ***
    • Posts: 15439
    • Country: fr
    Re: C word
    « Reply #113 on: September 25, 2019, 08:52:55 pm »
    Here is exactly what the standard says:
    Quote
    A conforming
    hosted  implementation shall  accept  any strictly  conforming  program. A conforming
    freestanding implementation shall accept any strictly conforming program that does not
    use  complex types  and  in  which  the  use  of  the  features  specified  in  the  library  clause
    (clause  7)  is  confined  to  the  contents  of  the  standard  headers <float.h>,
    <iso646.h>, <limits.h>, <stdarg.h>, <stdbool.h>, <stddef.h>, and
    <stdint.h>. A conforming implementation may have extensions (including additional
    library  functions),  provided  they do not  alter  the  behavior  of  any strictly  conforming
    program.

    "Hosted" is also mentioned as to how the main() function is handled.

    In practice, that basically means that a freestanding implementation 1/ doesn't provide ANY library (the standard headers mentioned above don't declare anything that's needed to be implemented as code outside the core language) and 2/ that it doesn't provide, by itself, any means of calling main(), thus you usually have to provide a low-level way of calling your entry function - most often in assembly code, some linkers may give you options to define a specific symbol as your entry point as well.

     

    Offline legacy

    • Super Contributor
    • ***
    • !
    • Posts: 4415
    • Country: ch
    Re: C word
    « Reply #114 on: September 25, 2019, 09:34:09 pm »
    It's not that C is "bad", it is just that

    it's not bad, it's just that it allows people to write shit like this.

    Good luck at making the code run on PowerPC e500, which already has its problems with cache, pipeline, etc  :-DD

    edit:
    two days spent at sanitizing u-boot. Now it works as it should, and even the blasted PCI does no more cause weird behaviors to the Linux kernel, this because if the firmware didn't properly initialize things ... ah, that's the true importance of the BSP :D

    ... the Sonoko project is costing me a lot of time time and effort, more than what I planned, but I have to say not so bad, in the end; at least Denx U-boot is of several orders of magnitude better than the piece of ugly and broken spaghetti code in the above link.
    « Last Edit: September 25, 2019, 11:49:23 pm by legacy »
     

    Online SiliconWizard

    • Super Contributor
    • ***
    • Posts: 15439
    • Country: fr
    Re: C word
    « Reply #115 on: September 25, 2019, 10:51:42 pm »
    Hmm, I have a problem with stack alignment on an AARCH64 processor. Anyone knowledgeable? ;D
     

    Offline magic

    • Super Contributor
    • ***
    • Posts: 7246
    • Country: pl
    Re: C word
    « Reply #116 on: September 26, 2019, 07:24:16 am »
    I suppose every call frame needs to be 16 bytes aligned like on x86-64?

    As long as you use a competent compiler that shouldn't be a problem, so what did you mess up? :D
     

    Offline legacy

    • Super Contributor
    • ***
    • !
    • Posts: 4415
    • Country: ch
    Re: C word
    « Reply #117 on: September 26, 2019, 11:33:28 am »
    Code: [Select]
    typedef struct object_t
    {
        union value
        {
            long  mword;
            char* string;
            void* stream;
            struct object_t * (*pfn)(struct object_t *);
            struct object * (*psyn)(struct object_t *, struct object_t *);
        } value;
    } object_t;

    object_t object1;
    ansi/C, the compiler considers "struct object_t" an incomplete type, and this trick can be used in declarations.

    Code: [Select]
    #include "types.h"

    typedef struct
    {
        union value
        {
            uint32_t mword;
            p_char_t string;
            p_that_t stream;
            p_that_t next;
            p_that_t (*pfn)(p_this_t);
            p_that_t (*psyn)(p_this_t, p_this_t);
        } value;
    } object_t;
    safe/C cannot use opaque-type, and each data MUST have its defined type, hence it introduces p_this_t and p_that_t as deferred-opaque (void*), hence the implementation needs unchecked converters to assign the deferred-opaque to object_t

    Code: [Select]
    object_t uc_obj_get(p_this_t p_this)
    {
        object_t object;
        object=p_this;
        return object
    }

    Code: [Select]
    define type pfn_t as function
    {
         in  is object_t;
         ans is object_t
    };

    define type psyn_t as function
    {
         in  is object_t;
         in  is object_t;
         ans is object_t
    };

    define type object_t as struct
    {
        value is union
        {
            mword  is uint32_t;
            string is string_t;
            stream is stream_t;
            pfn    is pfn_t;
            psyn   is psyn_t;
        };
    };
    Arise-v2 HL does three passes and automatically manages opaque types.

    Doesn't it look better? :D
     

    Online SiliconWizard

    • Super Contributor
    • ***
    • Posts: 15439
    • Country: fr
    Re: C word
    « Reply #118 on: September 26, 2019, 02:39:53 pm »
    I suppose every call frame needs to be 16 bytes aligned like on x86-64?

    As long as you use a competent compiler that shouldn't be a problem, so what did you mess up? :D

    It looks simple enough if you're not using assembly directly. But it's not necessarily. I'm using GCC. And writing low-level stuff in C.

    As long as you never define any alignment constraint, the compiler handles it.

    Accessing packed structs on the stack (local variables for instance...) royally sucks though, even when your accesses are perfectly aligned for each of the member you access (but obviously not necessarily to 16 bytes). Not sure if I messed up anything, if this is normal, or if there is any option I can configure. I tried the strict-align GCC option, but it didn't help. I would have at least expected some kind of warning from the compiler - but nothing. (Using the latest official ARM AARCH64 GCC compiler.)

    I have a lot of experience now with the x86_64 architecture, but I'm kinda new to the AARCH64 one. (First time I develop something for a 64-bit ARM CPU.) Oh well, this is getting off-topic. :D
     

    Online SiliconWizard

    • Super Contributor
    • ***
    • Posts: 15439
    • Country: fr
    Re: C word
    « Reply #119 on: September 26, 2019, 02:45:18 pm »
    ansi/C, the compiler considers "struct object_t" an incomplete type, and this trick can be used in declarations.

    Yup. Not quite sure, but I think it was even possible before ANSI C?
    This is not really a "trick". This is just akin to a forward declaration. If I'm not mistaken, you can also do this with typedef and struct/union.
    Such as: "typedef struct Toto_t; " and later define it completely: "typedef struct { ... } Toto_t;"
    IIRC, forward declarations were available in other languages, including Wirthian ones like Pascal, so I don't see them as particularly "unsafe".

    safe/C cannot use opaque-type, and each data MUST have its defined type, hence it introduces p_this_t and p_that_t as deferred-opaque (void*), hence the implementation needs unchecked converters to assign the deferred-opaque to object_t

    That sucks actually, because it kind of looks like it could make you shoot yourself in the foot much easier than with proper forward declarations.
    Weird rationale.
     

    Offline legacy

    • Super Contributor
    • ***
    • !
    • Posts: 4415
    • Country: ch
    Re: C word
    « Reply #120 on: September 26, 2019, 03:04:18 pm »
    Such as: "typedef struct Toto_t; " and later define it completely: "typedef struct { ... } Toto_t;"

    Like this?

    Code: [Select]
    typedef struct object_t; /* attempt to define an opaque type */

    typedef struct
    {
        union
        {
            uint32_t mword;
            p_char_t string;
            p_that_t stream;
            object_t next;
            object_t (*pfn)(object_t);
            object_t (*psyn)(object_t, object_t);
        } value;
    } object_t;

    it has never worked with GreenHills CC.

    Code: [Select]
    - compiling ex3 ... error
    line 3: useless storage class specifier in empty declaration
    line 11: unknown type name 'object_t'
    line 12: expected specifier-qualifier-list before 'object_t'

    Everything containing deferred-opaques must be isolated into special sections, where you apply the unchecked converters, this way the source can be submitted to AI-driven programs for checking.

    The AI is weak, and it needs this kind of "instrumentation".  :-//
     

    Offline Nominal Animal

    • Super Contributor
    • ***
    • Posts: 6967
    • Country: fi
      • My home page and email address
    Re: C word
    « Reply #121 on: September 26, 2019, 03:05:01 pm »
    it's not bad, it's just that it allows people to write shit like this.
    By that metric, Perl is horrible, and PHP is the spawn of satan.  I disagree: I just think the people who write shit like that should be educated to do better, or bashed on the head (with a cluebat, I'm not advocating physical violence here) to stop writing shit like that altogether.  They are tools for different tasks, and any tool can be misused.

    (Some tools are bad, like shovels with just a straight handle, without a crossbar grip at the end.  That grip makes a significant difference to the leverage a human can apply with the shovel, as well as the amount of energy a human spends to shovel a given amount of stuff from one place to another.  PHP is poorly designed as a language, because it tries to be everything for everybody, and ends up like a Swiss army knife with 537 different blades.  C is interesting as a language, because it truly is simple at its core; it is only when you include the standard C library, or other libraries or HALs, that make it an appropriate or inappropriate tool for a given task.  Because C does not need a runtime environment on most architectures, it is at the same time simpler, but also more versatile, than higher-level programming languages like C++.  Well, except that you can use a runtime-less subset of C++ also; that subset just isn't standardized in any way yet.)

    at least Denx U-boot is of several orders of magnitude better than the piece of ugly and broken spaghetti code in the above link.
    Have you noticed yet how much easier well-structured modular projects are to maintain?  I don't mean code with plug-in capabilities, I mean code that is structured and organized such that you can test or replace parts of it, with documentation explaining the purpose of each such part?  (Or dare I say, unit?  :P)

    And that the true sign of a master developer is in how intuitively descriptive (of the idea, not the code) the comments are?

    This is one part of why I like to help others learn to become better developers, on the web and elsewhere.  I myself am pretty good, but I am terribly slow, and detest writing code I see pointless (commercial programming work burns me out).  I've seen, in real life, how ... twisting? snapping? ... the point of view, their programming paradigm to be precise, for a new(ish) programmer, can give just enough boost to help them later create things I cannot, while incorporating those structural and documentation aspects; and that difference is definitely worth the effort.  Also definitely the occasional hurt: sometimes a sharp nudge is needed to keep eyes open to the reality.

    All my suggestions on how we should add to the standard C library (in the near term), and how we could derive a better replacement programming language for the same niche (or perhaps slightly closer to the metal, in the longer term), is just a continuation of that.  I do not fight against windmills like Don Quixote; I just go around telling people who care how to build better ones.

    Hmm, I have a problem with stack alignment on an AARCH64 processor. Anyone knowledgeable? ;D
    That depends on the cause of the problem.

    A few years ago, I did develop a workaround for using quadmath in GNU Fortran.  You see, on x86-64, malloc() returns memory aligned to 8 bytes, because that is the largest alignment required by any standard C data type.  However, quadmath uses SSE vector registers, and requires them to be aligned to 16 bytes.  The workaround is to override malloc() et al. (they are weak symbols, interposeable) with custom ones using memalign() et cetera.  Modifying gfortran frontend to generate memalign() calls instead of malloc() calls (i.e. intrinsic calls generated by the Fortran compiler) was too much of a spaghetti mess to unravel for me, compared to the workaround.

    So, if your problem is GCC or another compiler not generating the proper function preamble, good luck.  Even if you get your fixes approved, it'll take 2-3 years for the fixes to arrive in production, unless you can rope in one of the core developers.

    If, however, your problem is something like writing assembly code that interfaces to C functions correctly on AARCH64, or a process preamble that initializes the stack properly, I might be able to help.

    Such as: "typedef struct Toto_t; " and later define it completely: "typedef struct { ... } Toto_t;"
    Rather,
        typedef  struct Toto_struc  Toto_t;
        struct Toto_struc {
            /* Can use pointers to  Toto_t  or to  struct Toto_struc  here */
        };
    I like to use double spaces in typedefs, to make it easier to see the type being forward-declared, and the name it is declared as.
     

    Offline Nominal Animal

    • Super Contributor
    • ***
    • Posts: 6967
    • Country: fi
      • My home page and email address
    Re: C word
    « Reply #122 on: September 26, 2019, 03:07:39 pm »
    Like this?
    No.  Try
    Code: [Select]
    /* Forward-declare the type. */
    typedef  struct object_struc  object_t;

    /* Define the structure itself. */
    struct object_struc
    {
        union
        {
            uint32_t mword;
            p_char_t string;
            p_that_t stream;
            object_t *next;
            object_t (*pfn)(object_t);
            object_t (*psyn)(object_t, object_t);
        } value;
    };
    Note that next member must be a pointer, as otherwise you get infinite recursion within the type itself (p == p.next.next.next.next.next...next).
    « Last Edit: September 26, 2019, 03:09:27 pm by Nominal Animal »
     

    Online SiliconWizard

    • Super Contributor
    • ***
    • Posts: 15439
    • Country: fr
    Re: C word
    « Reply #123 on: September 26, 2019, 03:22:09 pm »
    Rather,
        typedef  struct Toto_struc  Toto_t;
        struct Toto_struc {
            /* Can use pointers to  Toto_t  or to  struct Toto_struc  here */
        };

    I forgot the struct name itself in the forward declaration. Writing what I did makes it gramatically ambiguous, because a "struct" keyword followed by an identifier is interpreted as the identifier in the "struct" namespace (oddity of C, probably coming from an old age... yes, struct, union and enum have their own namespace separated from the typedef namespace!) So with "typedef struct Toto_t;", the compiler would be expecting an additional identifier for the typedef.

    The following forward declaration is perfectly correct though:

    Code: [Select]
    typedef struct Something Something_t;

    typedef struct Something
    {
    int n;
    Something_t *pNext;

    } Something_t;

    So you can 1/ reiterate the "typedef", although it's not strictly necessary and 2/ use the typedef'ed type for struct members in the full declaration.

    Obviously you can't recursively use a struct in itself, so only derived types that are not recursive are allowed (typically a pointer!)

    You can also use forward declarations as "opaque" types (from which, here again, only pointers to them can be manipulated) by not exporting (making visible to others) the full declaration, like in the following.
    Code: [Select]
    // In a .h:
    typedef struct Something Something_t;

    // In the implementation source file (.c):
    typedef struct Something Something_t;

    typedef struct Something
    {...
    }    Something_t;

    you can of course omit the typedef here, and refer to it as "struct Something" everywhere, but I personally don't like that. It just looks inconsistent, and I "typedef" everything.

    Anyway, the opacity is not their only use. As seen above, one very common way of using forward declarations is for declaring structures with members that use a pointer to them (either directly or as a parameter of a function pointer, etc.)

    Note: you could of course do without all this, and use a "void *" instead, since all you can do is declare pointers to forward declared structs anyway. But you'd lose any type checking if you did this, which is unfortunate. So, I think forward declarations are pretty useful.
    « Last Edit: September 26, 2019, 03:41:03 pm by SiliconWizard »
     

    Offline legacy

    • Super Contributor
    • ***
    • !
    • Posts: 4415
    • Country: ch
    Re: C word
    « Reply #124 on: September 26, 2019, 03:48:59 pm »
    Code: [Select]
    typedef struct object_st object_t;
    typedef object_t* p_object_t;
    typedef struct object_st
    {
        union
        {
            uint32_t mword;
            p_char_t string;
            p_that_t stream;
            p_object_t next;
            p_object_t (*pfn)(p_object_t);
            p_object_t (*psyn)(p_object_t, p_object_t);
        } value;
    } object_t;

    Yup, this works on Gcc-v7-9 and GreenHills CC :D
     


    Share me

    Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
    Smf