Live data from Hacker News

Obvious things C should do

digitalmars.com

81–90 of 310 posts

Re: Obvious things C should do

#81

Header files are one of the things I miss the most about languages that aren't C. Having a very clear distinction between public and private, and interface and implementation is one of my favourite things about C code (at least the way I write it). Being able to just read through a library's .h files to know how to use it is really nice. Typically, my .h files don't really look like my .c files because all the docume…

I don't really program in C much so please correct me if I am wrong. There is a flaw in header files in that they work the exact same for dynamic vs static linking, right? If I am making a library in C for static linking, I need to put my internal details in the header file if I want the user's compiler to be able to use those details. But putting them in the header files also means they are part of the public interface now and should no longer be changed.

Basically, I cannot do something like a struct with an opaque internal structure but a compile time known layout so that the compiler can optimise it properly but the user cannot mess with the internals (in language supported direct ways).

Re: Obvious things C should do

#83
post #80

I'm not a c programmer, but having unit tests automatically run at compile time seems odd. If i wanted to run tests at the same time as compiling i would put that in the makefile.

Why is it odd? The compiler does all sorts of other checks based on things like static assert or type information.

Re: Obvious things C should do

#84

Yeah... no. Constexpr function evaluation sounds like a great idea until you start trying to use it, and get surprised when seemingly-constexpr-safe functions aren't constexpr. Or, you tweak one function and suddenly all your fancy compile-time unit tests explode. Ok, so you get around that with good code hygiene and by limiting the complexity of your constexpr functions... in other words, do the exact things we alre…

Just like constant expressions, a function run at compile time needs to be pure , which means no globals, no system calls, no I/O, no undefined behavior. Yes, that does constrain it somewhat, but D users have found it to be immensely useful anyway. There's really no comparison with preprocessor macros. All the preprocessor can do is trivial expressions with long values. Not even floating point. > you add a constexpr…

> D users have found it to be immensely useful anyway.

I think you're focused on something that D programmers found helpful, rather than focusing squarely on the needs of C programmers. C and D are both good languages. Their use cases can overlap, but frequently don't.

>=70% of the code I write for work is C, as I'm an embedded firmware dev. C meets the very particular needs of bare-metal development, a use case that continues to be underserved by Rust, Zig, and other supposed successors to C. So, I'll be approaching this with a strong bias towards that perspective.

To me, the argument about unit testing rings hollow because of all the other, far more complicated and runtime-subverting things that would also need to become standardized before it would be feasible to unit test C programs without help from the hideous hacks we use today, like CMock. So, all of that isn't doing anything for me.

> My proposal (and D) does not require constexpr. The same function can be used at run or compile time.

Like you, I dislike the constexpr keyword. But, particularly considering your own example of defining an enum value, I don't see how the "implicit const-evaluatable" approach makes my life easier. Calling functions to define an enum's value is cute, but I can't tell you why I'd actually want to do that. You mention that the preprocessor can't handle floats, but, well, neither can enums!

Adding a single printf (or, in my case, kprintf or LOG_DBG or whatever) would become liable to nuke some constant evaluation happening somewhere far up an obscure call chain. The basic reality of C is that you will, at one point or another, encounter a situation where your only debugging tool is print statements (or a single LED). That's the cold reality of C's paper-thin runtime.

So, I really dislike the idea of having a feature that's liable to make your code go "boom" at compile time because you put a print statement in just the wrong spot. Or a write to a memory-mapped register. Or a hard jump into a blob sitting somewhere in memory. Or inline assembly. Or a call to a function that uses any of those things, even once. Even without the keyword, you end up with red functions and blue functions. It's just harder to tell which ones are which.

Defining some const floats? Sure, that's neat. If you could use this feature to define huge matrices of floats, that'd be pretty cool! There's just a boatload of gotchas.

Re: Obvious things C should do

#85

C++ has all of these except forward referencing declarations(though Importing Declarations requires modules which nobody uses yet). I'm not sure why forward reference declarations is needed nowadays(or if it really is from a language standpoint). C could probably copy C++'s constexpr & static_assert stuff to get the first 2.

Nobody uses C++ modules because they are clumsy to use. D's are easy. Note: anyone is free to copy D's module design. It's the best one out there. > I'm not sure why forward reference declarations is needed nowadays The article gives reasons. Although they aren't necessary , they are deleterious to code layout which becomes a slave to the declaration order rather than aesthetic order. > C++'s constexpr is still laggi…

Robert Frost would approve

Re: Obvious things C should do

#86
post #80

I'm not a c programmer, but having unit tests automatically run at compile time seems odd. If i wanted to run tests at the same time as compiling i would put that in the makefile.

Why is it odd? The compiler does all sorts of other checks based on things like static assert or type information.

It's odd because you lose control over that aspect of compilation. It slows down the development loop because every time you do a build you have to wait for a bunch of unit tests that you don't care about yet.

Every time you do exploratory work you now have to comment out all the tests that this work breaks because otherwise it won't compile anymore.

That would be even more annoying than Go's stupidly pedantic compiler.

Re: Obvious things C should do

#87
post #4

It really reads like the author just wants Zig.

The author is the creator of D, so he's probably fine with D. And D is something like 25 years old. Whereas Zig is just a toddler.

ahh, that explains the ImportC comparisons. Also didn't realize that person is also a regular on HN as well.

Re: Obvious things C should do

#88
Some of my "obvious things c should do" for me would include things like

- add support for a slice type that encodes a pointer and length

- make re-entrant and ideally threadsafe APIs for things that currently use global state (including environment variables).

- standardize something like defer in go and zig, or gcc's cleanup attribute

- Maybe some portable support for unicode and utf-8.

Re: Obvious things C should do

#89

Earlier quoted context omitted.

the constexpr stuff has been around since the beginning[0]. concretely, what other thing from D do you claim zig has added since? [0] minimally 2019, 3 years in: https://youtu.be/Gv2I7qTux7g?si=p0kVhtB56GvVLLNr

D had compile time execution of functions in 2007. Order-independent top level declarations. Underscores embedded in integer literals. (I stole this idea from Ada, which had been forgotten. Soon after D popularized it, it became standard in other languages.) Continue or break to labeled loop. Fixed sizes for ints, longs, etc. Of course, I don't know if there's a straight line here, and Zig is welcome to use any featu…

>> Continue or break to labeled loop.

Hasn't Java had that since the beginning?

rummaging around in my grammar folder...

BreakStatement ::= "break" [ IDENTIFIER ] ';'

ContinueStatement ::= "continue" [ IDENTIFIER ] ';'

Re: Obvious things C should do

#90
while this is a very interesting take, I think the premise is a little bit to simple.

Firstly, there are at least 3 C compilers in widespread use, from apple, microsoft and gnu, these are a long way from 1 for 1 to each other so when it says for example:

->In other words, while C can compute at compile time a simple expression by constant folding, it cannot execute a function at compile time.

Maybe the compiler he tried cannot, but another can, no idea, it wasnt tested, they can be made to (the whole point of the article), apple and microsoft cannot be made to, everything in this article could have have been submitted as a merge request to gnu.... Article doesnt even state whose C compiler they embedded afaict.

wrt to "standard" c specifically, there are for sure some hard constraints on all the wild and wacky hardware support required that must make proposing and implementing changes within the c standard extremely hard, max respect to the anonymous experts that have got it to where it is today, but imho a lot of the "why doesnt c" questions can be as easily answered as "why doesnt V8 support 8 bit pic micros".

Post reply on HN