Oh, C3! - Page 1
Forum section: electronics / general

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 19, 2023, 04:11:45 am
content: https://c3-lang.org/

author: Whales
author_rank: Super Contributor
timestamp: April 19, 2023, 05:19:50 am
content: QuoteConvenient.QuoteWhy?QuoteThankyou to the authors for providing the rationale. I'm not involved in your group or the languages you are probably using as context, without this I'm clueless as to why you are doing many of your things.I like C as a low-level language, ie closer to assembly. Goto is natural for that. I'm worried that it sounds like you are placing compiler author desires ahead of users; what are these desires? Higher optimisation levels? That's a difficult sell to many C users, it's not an absolute problem, there are lots of shades of grey.I want to look more at this 'defer' feature, but I can't find much docs about it. Best I can do isthis examplebut it doesn't explain things like order of defer executions (stack or queue?), what happens to variable scope, whether I can defer an entire block of code (instead of just one line), etc.EDIT: removed my extra ideas, split into another post below.

author: Ed.Kloonk
author_rank: Super Contributor
timestamp: April 19, 2023, 05:21:44 am
content: Always the same. Based on C.QuoteOr when you're too lazy to write code that cleans up after itself.

author: Whales
author_rank: Super Contributor
timestamp: April 19, 2023, 05:28:31 am
content: I disagree with both you Kloonk AND the statements of the C3 authorsI hope that doesn't count as a double negative.There is lots to C I like. Definitely lots I don't like either. I'm not sure if C3 really floats my boat.I wonder what C3's use case and mindshare is? Narrowly in-operating-system programming mainly? Or broad inc micros? I can't find anything about that on the c3-lang.org site.TheC2 sitementions kernels & bootloaders.

author: Whales
author_rank: Super Contributor
timestamp: April 19, 2023, 05:36:39 am
content: Split from my earlier post, these are not comments about C3 but just interesting to compare with the lang changes they have made.Some things I've imagined up over the years whilst using C that I wish I had:(Whales1) Make the struct keyword unnecessary when using structs.Both options are annoying: having to write "struct" before every defintion (inc in function args) OR having to typedef every struct.This change would be backwards compatible with 99% of code (only breaking those that use struct names as names for something else too). If you want to keep using "struct" keyword everywhere you still could, no wakkas.(Whales2) Clamp down on a lot of the silliness you read being discussed about undefined behaviour.Do what the programmer would expect to happen on a standard 2's complement machine with type sizes a multiple of 8 bits. Use the rule of "least astonishment".C is supposed to be easier than assembly, don't make it harder.(Whales3) Require that ALL new arches/platforms adopt the same fixed definitions for the sizes of int, char, long, etc.I already use uint32_t and co from <stdint.h> but standard funcs like printf("%d") then require much uglier writing to be platform portable.eg printf("I have %"PRIu32" doges with %"PRIs64" coolness factor\n", dogcount, coolsum) is just a pain, even worse when you have many consecutive fields and less string inbetween.(Whales4) Syntactic sugar: namespaces.Implement just as an auto-prepending of function (and var?) names with the characters "namespacename::" and do nothing more. Also allow someone to strip these characters off again (ie skip the namespacename:: prefix when using the funcs) if they so desire.Completely optional, breaks nothing. Worth trying just to see if it makes things easier or harder to deal with. Many people already prefix their lib's function names with "LibName_" anyway, it might be better or worse to make an option of a standard method, not sure.(Whales5) Syntactic sugar: allow defining functions in a class-like syntax.ALL it does is automatically modify them to add a "self" argument to their arg list. No new/delete/constructor/deconstructor/public-private-protecgted stuff, leave that to Cpp, just a bit of sugar to make things a little neater and happier.Code:struct something{f32 posx, posy;char *name;void *aux;};something::new(u32 id);something::destroy();something::recolour(u8 r, u8 g, u8 b);Unlike C++ you wouldn't even need to expose all of the struct internals inside the header files, so editing the struct contents won't cause header files to change (which then won't trigger a recompile of absolutely everything). Eg this would be OK too:Code:struct something;something::new(u32 id);something::destroy();something::recolour(u8 r, u8 g, u8 b);(On the technical side: this is doable because then things don't need to know sizeof(struct) any more)

author: Ed.Kloonk
author_rank: Super Contributor
timestamp: April 19, 2023, 05:36:51 am
content: Quote from: Whales on April 19, 2023, 05:28:31 amI wonder if the adoption of these mutations sometimes comes from a project leader with certain pet-hates. But I see your point, a solution looking for a problem.

author: Whales
author_rank: Super Contributor
timestamp: April 19, 2023, 05:41:15 am
content: Probably a few different pet hates combined, the site lists 3 authors.Of course my pet hates are far superiorC (for better and for worse) has been shaped by the desires of many diverse groups, so it's hard and dangerous to claim you have improved it without taking into account a lot of diverse people's opinions OR intentionally stating that your modified version is for a narrower use case than the original.

author: DiTBho
author_rank: Super Contributor
timestamp: April 19, 2023, 09:16:03 am
content: Quote from: Whales on April 19, 2023, 05:41:15 amyup, in my case I can publicly declare I my modified version is for my narrower use case than the original, that's why it's called "my-c"I think c/89 and c/99 cannot be modified/improved too much if they have to serve diverse people's needs

author: newbrain
author_rank: Super Contributor
timestamp: April 20, 2023, 12:18:01 pm
content: Quote from: SiliconWizard on April 19, 2023, 04:11:45 amQuote from: SiliconWizard on April 13, 2023, 08:31:24 pmQuote from: madires on March 12, 2023, 02:21:19 pmYou guys are throwing me back to when I was (happily) subscribed to "Computer Language" magazine!Thank you!

author: Whales
author_rank: Super Contributor
timestamp: April 20, 2023, 12:42:35 pm
content: Quote from: newbrain on April 20, 2023, 12:18:01 pmThere are constant newlang discussions elsewhere. Checkouthttps://lobste.rsandhttps://news.ycombinator.com/I don't like newlangsbecause I want to give my programs the best chance of still compiling and running in 10 or more years time. C is not perfect, stuff still breaks, but it's better than most.

author: Ed.Kloonk
author_rank: Super Contributor
timestamp: April 20, 2023, 02:24:35 pm
content: Quote from: Whales on April 20, 2023, 12:42:35 pmAbsolutely.It's hard enough to re-acquaint the libs and deps, and then you've got some Martian language to deal with.It's a mid-level language that everyone eventually wishes it were high level.

author: DiTBho
author_rank: Super Contributor
timestamp: April 20, 2023, 02:37:23 pm
content: Quote from: newbrain on April 20, 2023, 12:18:01 pmwas/is it interesting?

author: DiTBho
author_rank: Super Contributor
timestamp: April 20, 2023, 02:59:40 pm
content: Quote from: Whales on April 20, 2023, 12:42:35 pmLOL, like "Fire-fLOP" (aka firefox) ? In 2005 I was able to compile it on my PowerBook G4.Now not only it's C++11 (requires modern gcc version) & Rust (requires llvm/clang) but building it eats more than 2GByte of rammy old laptop has 512Mbyte of ram, was able to compile the early versions of FireFox but .. today I only compile Dillo instead, ssh-tunneling to a proxy that makes it access to HTTPs web 2.0.Or, like the old Gentoo portage, that was python v1 && EAPI={1 , 2}?Now it's Python >=3.*, EAPI={ 5 , 6 , 7 , 8}, no more compatible with previous ABI.Code:case ${EAPI} in5) ;;6) ;;7) ;;8) ;;*) die "EAPI=${EAPI} is not supported" ;;esac----> forget your old Overlays, forget ***every*** single old portage: old stuff won't work on modern stuff.And I have no solution, except an ugly hybrid merge-up(1) for my old router (2008); while for the new one router (2020) ... I am all with 2023 stuff, and expect (hope?) it will work for the next 5-8 years.Or, like Perl, autodoc (Latex?), and other scripts used in Linux Kernel?can you still compile kernel 2.0? no -> need to be fixed, but you'd best use an old rootfscan you still compile kernel 2.2? no -> need to be fixed, but you'd best use an old rootfscan you still compile kernel 2.4? no -> need to be fixed, but you'd best use an old rootfsCan you still compile kernel 2.6? no -> need to be fixed, but you'd best use an old rootfsCan you still compile kernel 3.*? somehow yes, but ... it's full of pain, and you'd best use an old rootfsSo, I am afraid that it's not only the language but rather everything from the kernel up!(1) basically it's still a 2008 stage4, integrated with a forced multi-library or static-linked (I know, it's wrong by design, and consumes more space ... but at least it works) to have some modern stuff on it, like modern OpenSSL, modern OpenSSH, modern curl, and modern wget, all able to work on "https" and SSL stuff.

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 20, 2023, 07:22:25 pm
content: Quote from: newbrain on April 20, 2023, 12:18:01 pmI have posted quite a few of these. These new programming languages make an almost endless list!Most of the corresponding threads, the "yet another one" series I have started are more for a quick fun than anything else.Many are sort of "funny", some are interesting. As I said previously, I think Zig would fit in the interesting category. Another one would be Odin.The guy behind Odin, which is nicknamed gingerBill, has interesting stuff to say, and he's very humble.That doesn't mean you should actually use any of these languages, but still can be interesting to look at.Generally speaking, looking at stuff that you're not constantly being told to look at is not a bad move.

author: newbrain
author_rank: Super Contributor
timestamp: April 20, 2023, 08:33:49 pm
content: Quote from: DiTBho on April 20, 2023, 02:37:23 pmFor a young EE studying nerd? Quite a lot!Readthe number with the interviews to Knuth and Wirth.But TBH, my original subscription was forMicro Cornucopia, a treasure trove of hardware and software information, which unfortunately folded shortly after I paid my second year.They offered to transfer the subscription to a small number of magazines - remember those?I selected CL as I was buying it already from time to time.

author: Siwastaja
author_rank: Super Contributor
timestamp: April 21, 2023, 06:43:24 pm
content: I find it hilarious they absolutely had to removegoto, but then creep in a feature of adding a new kind of goto which can arbitrarily jump around inside switch-case: something no one ever asked, switch-cases being quite confusing already as they are.

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 21, 2023, 08:08:33 pm
content: Quote from: Siwastaja on April 21, 2023, 06:43:24 pmAs I've seen, they removed the need for 'break' inside switch's, making them behave as the Pascal/Ada 'case' constructs by default. But then added the 'nextcase' statement to allow falling through.'nextcase' doesn't allow to jump around freely but only to the next 'case', as I've got it at least.In order words, they inverted the default behavior in switch-case, which is not a completely stupid idea.You're wrong in saying "no one asked for that". Fallthrough is the only way of combining multiple cases. People use that all the time. And so, once you decide to remove the fallthrough behavior as default, this 'nextcase' statement is the logical step. You need it, unless you give up on having multiple cases leading to the execution of the same code.The problem is that it's a half-baked solution: outside of cryptic constructs like the Duff's device, using fallthrough in switch-case in C was mostly meant to emulate the possibility of having cases for multiple values instead of just one. That was much better addressed even in Pascal (if I remember it right) using ranges.But obviously a 'nextcase' statement is much easier to implement.

author: Siwastaja
author_rank: Super Contributor
timestamp: April 22, 2023, 05:39:34 am
content: Quote from: SiliconWizard on April 21, 2023, 08:08:33 pmNo, look closer - clearly that was their original idea, but they feature creeped their "fallthrough" to take an argument, allowing you to jump to any other cases, in any order. I'm ridiculing this feature.I agree with the inversion from implicit fallthrough to making it explicit. Not only it saves from typing boilerplate (break is the usual case), it reduces human error.

author: Karel
author_rank: Super Contributor
timestamp: April 22, 2023, 06:25:52 am
content: Here we go again. Is there somebody who really believes C is going to be replaced?I don't for various reasons. C has been here for a long time and it will stay here for even a longer time.I agree though, it's fun to watch the attempts and it can be interesting to analyze them.

author: newbrain
author_rank: Super Contributor
timestamp: April 22, 2023, 06:29:28 am
content: Quote from: Siwastaja on April 22, 2023, 05:39:34 amBut why?It's so beautiful!Now you don't need if, while, do and for.Every structured flow control can be achieved with a suitable switch statement!/s, in case it's needed.I don't find the nextcase feature (even the basic one) especially compelling.In a way, it's already there in C as compilers warn when falling through cases.Break is still there, (and the possibility of leaving named scopes is indeed nice) this just removes one of its uses.

author: DiTBho
author_rank: Super Contributor
timestamp: April 22, 2023, 10:53:54 am
content: Quote from: Karel on April 22, 2023, 06:25:52 amthere are only to kinds of people: those who are spending time wondering *** if *** { C/89 , C/99 } could be replaced ... (and with what?) and those who have actually already replaced (improved? just modified? just made it weirder? ... mumble, dunno what's the correct verb here) C and re-written a small uKernel as well as a b+tree filesystem, and are very happy that it took just 1/4 of the effort was taken with C/89

author: Karel
author_rank: Super Contributor
timestamp: April 22, 2023, 11:51:32 am
content: Quote from: DiTBho on April 22, 2023, 10:53:54 amI always use gcc with option -std=gnu11. No problems here, programming has never been easier using GNU/Linux, make and GCC.Not saying here that everybody should do like me. Just telling what works best for me.

author: DiTBho
author_rank: Super Contributor
timestamp: April 22, 2023, 01:16:34 pm
content: Quote from: Karel on April 22, 2023, 11:51:32 amfrankly I feel really frustrated by answer like this.

author: Karel
author_rank: Super Contributor
timestamp: April 22, 2023, 01:30:07 pm
content: Quote from: DiTBho on April 22, 2023, 01:16:34 pmPlease don't, it's not worth it. Use what works best for you.

author: JPortici
author_rank: Super Contributor
timestamp: April 22, 2023, 05:01:30 pm
content: IMHO the only thing that C ever needed is a .length attribute for arrays.I'm sick and tired of bugs introduced by using sizeof() on an array when you should have used sizeof(a)/sizeof(a). Looking at you, handsome guy in the mirror pointing at me.

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 23, 2023, 08:54:50 pm
content: Quote from: Siwastaja on April 22, 2023, 05:39:34 amOh, you're right. You had a closer look than I did.There's this infamous "labelled nextcase".https://c3-lang.org/statements/#nextcase-and-labelled-nextcaseIt's not even merely a "label", it's an expression that can be evaluated at run-time and this acts as though the code flow was looping back to the switch select with a value given by the "label" (which again isn't a label.)That doesn't look good.Oh, and incidentally, with this construct, if the expression given to nextcase evaluates to a value that is not handled by any 'case', then it becomes an infinite loop. Nice!!Or does the switch just exit in this case? Who knows, not sure I saw that clearly.That said, the guy maybe had the typical state machine construct in mind. For which I would favor setting a variable with the next state, rather than directly controlling the flow anyway.His approach avoids having to put the switch inside a loop, but then it makes a potentially implicit loop, which is horrific.The benefit of using a variable holding the state is that it's much easier to trace. If you control the flow directly in many places, it makes tracing much more tedious.

author: PlainName
author_rank: Super Contributor
timestamp: April 25, 2023, 06:45:31 pm
content: QuoteAll my project have:Code:#defineARRAY_SIZE(x)(sizeof(x) / sizeof((x)))

author: Nominal Animal
author_rank: Super Contributor
timestamp: April 25, 2023, 07:19:46 pm
content: Ever since the last C-related programming language discussion, I've now and then examined the typical cases where human programmers make most errors in C.I'm pretty darned convinced that the only fundamental change (in addition to various syntax etc. additions we have discussed here in other threads previously), would be to replace pointers with arrays as the base memory reference type. (There are details wrt. read-only strings I'm not sure about, though.) That would let the compiler do compile-time memory access validation, helping kill buffer-related bugs. All other changes could be done incrementally, by replacing the C standard library.Whenever I do such experiments –– i.e., how would code look like and what would it compile to, if I tweaked the compiler and librariesjust so–– I always discover that the end result I desire is obtainable by a smaller 'real' change (but large paradigm/approach/theory-wise change) than one would initially assume or believe. Furthermore, the things most developers get stuck on –– myself included, unless I monitor myself to explicitly avoid this ––, end up not affecting the actual language use much; only how it looks like on the surface, and how it can be described to other people. Unimportant fluff, in other words.To repeat from those other threads, I would like additional features that provide an unordered (data-parallel) for loop constructs, as well as a way to tell the computer that two independent code sections can be interleaved (that their relative order is unimportant, perhaps at block level). But these are optimization, things that are somewhat difficult for compilers tooptimizeusing current C rules; and I have not verified what kind of constructs would be needed and what kind of changes needed to the C standard abstract machine model to address these. The all-pointers-are-actually-arrays change, however, would be suprisingly straightforward.

author: PlainName
author_rank: Super Contributor
timestamp: April 25, 2023, 08:36:25 pm
content: QuoteWhy would that be better?

author: DiTBho
author_rank: Super Contributor
timestamp: April 25, 2023, 09:43:49 pm
content: Quote from: PlainName on April 25, 2023, 08:36:25 pmbecause they can transport borders and size { begin, end, size }

author: Nominal Animal
author_rank: Super Contributor
timestamp: April 25, 2023, 09:53:48 pm
content: Quote from: PlainName on April 25, 2023, 08:36:25 pmIt makes it possible for the compiler (with current gcc and clang static analysis/warning capabilities) to verify buffer accesses are valid. (That is, the compiler knows at compile time if each access is "valid" (safe, within the buffer), "invalid" (overrun/underrun), or "undetermined"; with the last one only affecting code that uses pointers or tricky indexing math whose limits are unknown at compile time.)To explore this yourself, write some test code using the patterntype1 somefunc(size_tlen, type2buffer, ...)i.e. instead of pointers, you pass an array; and to avoid having the array auto-decay to a pointer, you need to specify its size too.If you introduce a typical buffer overrun bug in such a function, no matter how deep in a call chain, the compiler will tell you if you enable the relevant warnings. There are no added run-time checks at all; look at the generated machine code too.This alone does not do anything for existing code, say for examplestrlen(). The idea is to use the change to rewrite the standard library in a form where pointers are replaced with array references. Currently it is a bit cumbersome, for examplestrlen()would best be written asssize_t strlen(size_tlen, const char s);so at minimum we'd need the compiler to allow the size of a parameter array to be defined later in the explicit parameter list (withssize_tfrom stolen from POSIX; C currently usesintfor it, which is problematic on LP64 architectures).The necessary changes, as I said, are surprisingly small. The effects, however, to how easily statically analyzable it makes efficient code, are surprising. You really do need to experiment with it to see the possibilities. As I also said, read-only/immutable strings have peculiarities I'm not sure yet how best to deal with, but basically the rest of POSIX C -like functionality (i.e., with different API/function signatures, but same or very similar functionality) is quite straightforward. Oh, and functions allocating or reallocating memory, returning an array reference, may need syntactic sugar (as currently they really need to return a struct containing the start address of the allocated memory, and length in bytes).(What I am not sure about yet, is whether we need a new non-scalar base "type" with two properties, start address and length. Currently, we can do that and slicing (three properties: start address, step size, and count), just fine using structures. But there might be additional compiler optimization/compile time static analysis opportunities, if it was a base type to begin with.)

author: PlainName
author_rank: Super Contributor
timestamp: April 25, 2023, 10:02:12 pm
content: Quote from: Nominal Animal on April 25, 2023, 09:53:48 pmAh! Of course, I was stuck in pointer mode thinking the array would be passed as a pointer and just look like an array to the programmer. But I see now that's not the idea

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 25, 2023, 11:11:07 pm
content: That's more or less akin to always using the base pointer to an allocated block (rather than accessing it through a pointer that could point arbitrarily inside, or even outside of it) and some index for accessing its content. You also need to store the size.After which it does look like a full-fledged array indeed.That's something you can always do in pure C though, even if that means a bit more programming overhead and possibly a bit less opportunity for optimization (even though that would remain to be seen in practice.)I have written a header file years ago, that I still use to this day (with some minor evolutions), that exposes a few macros to encapsulate dynamic memory management, including "dynamic arrays", which are accessed via indices only (either with, or without bounds checking depending on the use case.) I haven't directly called any malloc/realloc/free ever since. The runtime overhead is either zero or extremely small.Sure having that built-in would be nice, but point is, this approach can still be - at least in essence - used without designing a new language. I for one wouldn't use C without this small "library" I wrote more than a decade ago, at least for anything requiring dynamic allocations. For pure static allocation stuff, part of it can still be used.The basic idea is to create a type for your 'arrays', something like this:Code:typedef struct{BaseType *Block; // pointer to your memory block, from static or dynamic allocationsize_t n; // current number of items of type 'BaseType' in the memory blocksize_t nMax; // max number of items of type 'BaseType' in the memory block} Array_t;That can be initialized from a statically-allocated array just like so:Code:BaseType Array;Array_t MyArray = { .Block = Array, .n = 0, .nMax = ARRAY_SIZE(Array) };The variant for dynamically-allocated arrays is also easy. With this simple construct, one can see that handling dynamic arrays becomes 'straightforward'.Accessing it is just:Code:MyArray.Block // no bounds-checking, can be used with zero overhead when guarantees about 'index' are sufficientMyArray.Block[index < MyArray.n? index : MyArray.n - 1] // bounds-checking, default to "saturating" the index// You can add variants of bounds-checking that will execute some code in case of an out-of-bounds condition if needed.With a few macros, that can be declared, and manipulated for just any base type very easily.Some will find that clunky, especially if they don't like macros, as doing this without macros will be even clunkier.Others will do this kind of stuff with macros and move on.In any case, you'll indeed realize that directly playing with pointers is rarely necessary, and can be left to the very occasional and very low-level stuff.The benefits of keeping all your pointers only pointing to *objects*, rather than potentially pointing arbitrarily *inside* an object are multiple.

author: PlainName
author_rank: Super Contributor
timestamp: April 25, 2023, 11:43:22 pm
content: I do a similar thing but use functions rather than macros. There's an overhead in the function call, but more scope to mess around when debugging without affecting anything else. Also doesn't rely on the programmer remembering to use the safe access when appropriate

author: Nominal Animal
author_rank: Super Contributor
timestamp: April 26, 2023, 12:12:52 am
content: It is very interesting (but unclear) to me exactly why most C programmers – myself included – preferrettype funcname(elemtype *ptr, size_t len);overrettype funcname(size_t len, elemtype buf);even though the only difference in machine code is the order of parameters; but the latter API pattern allowing much better buffer access checking at compile time, even through deep call chains (each call limiting to a smaller sub-array), helping catch buffer underrun/overrun errors.The easy answer isinertia(or habit or familiarity or because everyone else does it that way too), but I'm not sure it is the whole answer.Isn't it interesting how rarely anything like this (arrays-not-pointers) is suggested for "the next C", even though memory or buffer over/underrun bugs are the most common issues in C code?Quote from: PlainName on April 25, 2023, 10:02:12 pmYep. It's more like a cultural change than a technical one, even though its purpose is purely technical: help with compile-time static analysis wrt. buffer accesses.Quote from: SiliconWizard on April 25, 2023, 11:11:07 pmActually, what I want is for the compiler to be aware of the size whenever it is known at compile time.If you consider the twofuncname()definitions at the beginning of this post, you can clearly see the difference between the pointer and the array approach. This difference is the critical one; it isnotabout adding explicit size information to interfaces that currently use a pointer only. (Except for memory allocation functions: these should return both the allocated size and the base address, instead of just the base address. This would actually be desirable in many grow-as-needed use cases, considered completely separately. Oh, and possibly the string functions, which deserve to be redesigned anyway.)Quote from: SiliconWizard on April 25, 2023, 11:11:07 pmNote that the change would not cause any change to runtime code, no inherent additional runtime memory or CPU overhead at all.Many string functions would actually add an explicit size parameter (ABI-wise), but I consider that a plus (and a deficiency in current standard C library string functions). I've discussed the related issues especially in embedded environments before; let's just say that string handling can be done much better (faster, more reliably) even in current C than what the standard C library provides.Passing an array forwards is trivial even in current C (since C99), although the size of the array must be before the array in the parameter list, butreceivingan array from a function call is not supported. Thus far, in my experiments I've simply assumed syntax "elemtypearrayname = ...;" (declaring two variables at once, initialized by a single function call returning both the base pointer and the size, with the size divided by the element size to obtain the count "automagically"), but I'm sure better syntax can be devised.Quote from: SiliconWizard on April 25, 2023, 11:11:07 pmYes, I use this pattern extensively. For some reason, I use 'used' for the current number of items, and 'size' for the maximum number of items, and 'item' for the pointer or C99 flexible array member. It is very common to see a variant oftypedef struct {size_t size;size_t used;elemtype item[];} elem_array;in my code.Indeed, whenever this information is already available, why don't we tell the C compiler about it, so it can help check the array boundaries for us at run time?This is the core of this suggestion. Not to add size and/or used to everywhere (except functions that in my opinion should have had the size from the beginning even in the standard C library), but to help the compiler understand better exactly what us humans intend, and help catch our thinkos at compile time.

author: DiTBho
author_rank: Super Contributor
timestamp: April 26, 2023, 08:54:36 am
content: Quote from: Nominal Animal on April 26, 2023, 12:12:52 amactually I do preferans_t funcname(buffer_t buffer)

author: DiTBho
author_rank: Super Contributor
timestamp: April 26, 2023, 09:08:11 am
content: Quote from: Nominal Animal on April 26, 2023, 12:12:52 ameven better, why don't we tell the ICE about it? so it can help automatic test-cases and autonomously check boundaries for us at run time?even better++, why don't we facilitate AI-assisted ICEs? So they can also use that information to identify common patterns in pieces of code that have a high probability of containing bugs.

author: JPortici
author_rank: Super Contributor
timestamp: April 26, 2023, 10:20:59 am
content: Quote from: PlainName on April 25, 2023, 06:45:31 pmof course, and i should do that.However a lengthof(x) operator that can only take arrays as an input would have been better than a macro (ISTR lengthof as an extension in some compilers)

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 26, 2023, 08:40:00 pm
content: Quote from: PlainName on April 25, 2023, 11:43:22 pmSure, problem is that you can't avoid macros to generate the type definitions themselves (such as the Array_t example I gave, for any given base type.)You can kind of work around it by using a void * pointer for the allocated block and add an additional member for the 'element size', but then you lose any basic static check, and you suddenly get an even better way of shooting yourself in the foot than directly messing with pointers.Or you hand-write every 'array' type definition, which is horrible. Macros are for avoiding to retype the same text over and over again, and that's what I use them for.Want to add a member to your 'generic' type? Just modify the macro. Macros need some care to avoid the usual pitfalls, but when used with some care, they are infinitely preferable to duplicating code.

author: Siwastaja
author_rank: Super Contributor
timestamp: April 27, 2023, 09:06:56 am
content: Quote from: SiliconWizard on April 26, 2023, 08:40:00 pmAnd I truly believe the C preprocessor is one of its strongest points and reason why C became so popular. People who invent "C replacements" tend to miss this fact. The first thing they do is they remove the preprocessor because it's so inelegant and dangerous; yet fail to come up with something with at least the same capabilities.C programmers have this love-hate relationship with the preprocessor. It's horrible, but it's surprisingly powerful and makes it possible to do generic programming in C.

author: DiTBho
author_rank: Super Contributor
timestamp: April 27, 2023, 11:23:51 am
content: Quote from: Siwastaja on April 27, 2023, 09:06:56 amsure! why not? in fact cpp was the first thing being banned and removed entirely in my-cIt can be done, and my-c doesn't miss anything, just it solves problems differently and makes life easierWhereas C/89/99 ... well, the last bug i fought in the Linux kernel was a typo with "#define something SPACE MISTAKE etc" which got through the build Gcc-v12 steps but caused a silent but catastrophic and sneaky bug, and I wasted three weeks on it

author: DiTBho
author_rank: Super Contributor
timestamp: April 27, 2023, 11:31:56 am
content: Quote from: Siwastaja on April 27, 2023, 09:06:56 amAlso, include those who write analysis software and develop ICE tools.For all of us cpp is more than terrible.

author: Siwastaja
author_rank: Super Contributor
timestamp: April 27, 2023, 01:55:14 pm
content: CPP = C Plus Plus

author: DiTBho
author_rank: Super Contributor
timestamp: April 27, 2023, 02:08:10 pm
content: CPP = C Pre Processorbelongs tosys-devel/gcc ---> /usr/$arch-$computer-linux-gnu/gcc-bin/$gcc_version/cppdev-lang/gcc_gnat ---> /usr/$arch-$computer-linux-gnu/gnat-bin/$gcc_version/cpp(gcc_gnat is ... gcc + gnat_ada_core, recompiled as gcc with languages={C, Ada} )c++ = C plus plusg++ = GNU C plus plus

author: DiTBho
author_rank: Super Contributor
timestamp: April 27, 2023, 02:18:08 pm
content: cpp also belongs tooverlay@idp: sys-devel/my-c~MIPS5++ ---> /usr/idp/my-c-bin/$my-c_version/cppwhat?didn't you say that cpp was banned?Yup!So why iscppthere in the my-c tree?to cure your inertia at being tempted to invoke it with ... random punishments in form of- console blocked for 5 minutes (like with the "SL" ncurses program)- you cannot do nothing but get your random insults, ncurses full screen(so at the end of the day you would like to DELETE it, and you cannot because you don't have root permissions)

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 27, 2023, 07:41:13 pm
content: Quote from: Siwastaja on April 27, 2023, 09:06:56 amI personally don't hate the preprocessor at all - I find it very useful.Yep, every attempt at replacing the preprocessor to achieve the same level of generic programming have either led to something much less flexible/powerful, or true untamable and unverifiable monsters.What many people seem to miss - and that Wirth has kept saying over and over again - is that simplicity should be a goal.C is simple, the C preprocessor is simple.C++ templates are monsters.

author: DiTBho
author_rank: Super Contributor
timestamp: April 28, 2023, 10:14:54 am
content: Quote from: SiliconWizard on April 27, 2023, 07:41:13 pmevery attempt? except my-c, so it's some but not all

author: DiTBho
author_rank: Super Contributor
timestamp: April 28, 2023, 10:20:45 am
content: even replacing #define macro() in cpp with a true compiler built-in macro() mechanism is bettereverything that doesn't pre-process the source is better because it doesn't hide information

author: PlainName
author_rank: Super Contributor
timestamp: April 28, 2023, 10:39:41 am
content: QuoteBut isn't that one of the main features of functions? They hide lots of nitty gritty detail behind a simple name (and, of course, let you reuse code without repeating it, which is also what macros can do).

author: DiTBho
author_rank: Super Contributor
timestamp: April 28, 2023, 03:26:26 pm
content: macros (by cpp) vs functions:- functions are not pre-processed but compiled- macro does not check any Compile-Time Errors, Function checks Compile-Time Errorsthe second is what I meant: you lose information during pre-processing.

author: Siwastaja
author_rank: Super Contributor
timestamp: April 28, 2023, 03:45:24 pm
content: Quote from: PlainName on April 28, 2023, 10:39:41 amDiTBho means it hides information otherwise accessible to his own automated analysis tool. The options are obvious, either go through the hassle of making that analysis tool understand macros (thus nothing would be hidden), or ban the use of macros. DiTBho has clearly chosen the latter and it's understandable as it's less work for him.For example, modern C compilers have "understood" preprocessor (I think by producing metadata from the preprocessing step and forwarding it to the compiler) and not just blindly do text replacement as a separate preprocessing step; they can produce good error messages. The same idea could be followed in DiTBho's "ICE".

author: DiTBho
author_rank: Super Contributor
timestamp: April 28, 2023, 04:08:45 pm
content: Specifically, there are three kinds of code repetition:type-1, the repetition that can be avoided by using "functions"type-2, the repetition that can be avoided by using "trivial macros"type-3, the repetition that can be avoided by using "complex macros with loops/recursion"Which brings to what experienced C/{ 89, 99} programmers feel as "tagged patterns of code repetition".Which brings the question: to avoid it, can pure C benefit from meta-programming?Which brings the final question: since there is no other mechanism in C/{ 89, 99}, can the C pre-processor-macro be *the right tool* for some decent meta-programming?The answer is:NO.Technically it can be done, but it's practically too error prone.What you want here is a replacement of the pre-processor, something built-in the language that allows you to eliminate code repetition by using macro iteration and with the complete support for algebraic data types and interfaces.Your goal is also to reduce boilerplate and the risk of a failure.And about that, I want to make myself clear: you need it strictly this way and nothing more. C++ does more than is required, making it a dangerous template meta-programming monster.

author: Siwastaja
author_rank: Super Contributor
timestamp: April 28, 2023, 04:32:38 pm
content: The right balance between "stupidly simple and thus dangerous" and "too elegant and thus dangerous" is very difficult to achieve. What sounds nice on a CS department coffee room easily gets out of hands.One-man project is likely to go less catastrophically wrong than something designed for years by a committee, so I'm sure your-C has better generic programming ideology than C++

author: PlainName
author_rank: Super Contributor
timestamp: April 28, 2023, 06:32:42 pm
content: QuoteThat's a backroom issue though. Kind of like driving a car and saying this one is trash because the engine is petrol rather than diesel. On a technical level it can make a difference, but if you're having to deal with that regularly I think something is wrong.QuoteNot sure I get what you're saying there: doesn't a macro error result in a compiler error?

author: PlainName
author_rank: Super Contributor
timestamp: April 28, 2023, 06:34:53 pm
content: QuoteSure, nowt wrong with that. I would do the same if I was making the stuff he was. But I don't think it's legitimate to say something is bad everywhere with no redeeming features because of some personal thing no-one else will encounter. And it's the general that I thought we were talking about here.

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 28, 2023, 06:58:09 pm
content: Quote from: PlainName on April 28, 2023, 06:34:53 pmAgreed, but to be fair, that tends to be the attitude of *most* people having designed programming languages, with only a very few exceptions.

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 28, 2023, 07:14:05 pm
content: Quote from: Siwastaja on April 28, 2023, 03:45:24 pmWhat it hides to what (or whom) is the question here.To the programmer, macros "abstract" pieces of code, so in that regard they "hide" code, but in a similar way other language abstractions do, as PlainName suggested.Now the reverse happens for static analysis tools and compilers (usually): the code they analyse is the preprocessed code, and in that regard, macros hide no code to these tools. It's the converse: in that context, macros hide... the macros themselves, not the code they generate, as it's preprocessed.Sure some more elaborate tools can "understand" macros (instead of merely preprocessing them before analysing the code) so the analysis can link to the original macros, which can be handy to... "debug" macros. Otherwise, it may not be that useful, you usually have line numbers to look at the original source code in case.I think the main concern people have with macros is that they find it hard to prove the correctness of the code generated by macros - in other words, the correctness of macros themselves.I've personally never introduced bugs due to macros I've written, that I can remember of, but I may be an alien, who knows.Now if you still want/need to validate your macros as the rest of your code, you'd do just as you do for the rest of your code. Write "unit tests" for your macros. It's not rocket science.

author: PlainName
author_rank: Super Contributor
timestamp: April 28, 2023, 08:24:25 pm
content: QuoteThey can turn into a write-only language. Especially with heavy use of ##.

author: Siwastaja
author_rank: Super Contributor
timestamp: April 29, 2023, 05:33:20 am
content: Quote from: PlainName on April 28, 2023, 08:24:25 pmIgnoring DRY and copypasting is way way way worse than a difficult-to-read macro.Copypaste / search-and-replace bugs happen and they happen a lot. Also difficult to notice for a human reader; in 9 places out of 10, correct type/variable is used, but in one spot... Compared to that, a hard-to-understand macro is much better. Maybe it's hard to read, but you need to read and understand that only once, and then it produces perfect automated copy-paste each time used.# and ## magic is pretty essential in many types of projects (for example, many different message types in a message processor), because the only other options would be getting rid of most typechecking and writing everything around void* pointers and generic buffers; or copypasting and manually modifying code gazillion of times. Both much worse.

author: PlainName
author_rank: Super Contributor
timestamp: April 29, 2023, 07:46:00 am
content: I guess it depends. From a user perspective, this kind of thing can be tricky:Code:return _lv_obj_get_style##style_type (obj, part, LV_STYLE_##prop_name);It defeats editor/IDE lookup tools to figure out what it means, so while it no doubt helps the original author (and a user not trying to debug it) it's a drag for anyone else. This is one of the decent uses - I've seen much, much more user-hostile stuff.

author: Siwastaja
author_rank: Super Contributor
timestamp: April 29, 2023, 07:56:21 am
content: Doesn't look too nice, but isn't the alternative copy-pasting and search/replace the whole function? Possibly tens of times? That's just disastrous. Generic programming isneeded. In C, that's using preprocessor. In C++, either preprocessor or template system. Generic programming never looks as simple as non-generic, no matter how well designed the language is. It's still super useful.

author: PlainName
author_rank: Super Contributor
timestamp: April 29, 2023, 08:06:15 am
content: QuoteNo idea - I gave up trying to figure out what it all means

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 29, 2023, 07:46:23 pm
content: "Obvious" tips to help with macros.First, document your macros as soon as they are non-trivial. Funnily enough, I've seen A LOT of code in which the C code itself was heavily commented, but macros, almost NEVER.Then, as I suggested earlier, if you want to be sure of your macros (or someone else's) and you have doubts, just TEST them.Just because they are macros doesn't mean they are out of scope for testing.Testing is not difficult.Write test files that include the macros you want to test (ideally your macros sit in header files so just include the corresponding header files), and a bunch of test cases. It doesn't have to be C code at all. Just a series of macro invocations. Write the expected output in separate files.Run the preprocessor on these test files and compare the outputs with your expected outputs with diff. All this can be fully automated.

author: PlainName
author_rank: Super Contributor
timestamp: April 29, 2023, 09:54:27 pm
content: I think the issue with stuff like ## is the levels of redirection. We can keep in mind up to 7 levels (if we're good - most people aren't) and a #define is already one level. So you can sit and work it out and even write test cases and know what it does, but then trying to apply that in realtime to what you're looking at is like speaking Spanish while reading Mandarin. And, as I note, the usual tools that let you find, say, a function definition and its associated comments, don't work with this type of macro so you can't easily find any comment either.

author: cfbsoftware
author_rank: Regular Contributor
timestamp: May 09, 2023, 12:31:15 am
content: Quote from: SiliconWizard on April 21, 2023, 08:08:33 pmFTR, Standard Pascal has case label lists e.g.case ch of'a', 'e', 'i', 'o', 'u': chtype := vowel;......This was extended in Modula-2 to include case label lists and subranges e.g.CASE ch OF'a', 'e', 'i', 'o', 'u': type := vowel |'0'..'9': type := digit |......