Live data from Hacker News

The C23 edition of Modern C

gustedt.wordpress.com

201–210 of 360 posts

Re: The C23 edition of Modern C

#201
post #61

Earlier quoted context omitted.

C++ can seamlessly include C89 headers. The C library headers for libraries I write often include C11/C99 stuff that is invalid in C++. Even when they are in C89, they are often incorrect to include without the include being in an `extern "C"`.

Clang supports C11 - 23 in C++, as well as some future C features like fixed-point integers. The main pain points with Clang are just the fundamental differences like void* and char, which don't typically matter much at an interoperability layer.

There's a lot of subtle differences between 'proper' C and the C subset of C++, since C++ uses C++ semantics everywhere, even for its C subset.

Many C++ coders are oblivious to those differences (myself included before I switched from 'mainly C++' to 'mainly C') because they think that the C subset of C++ is compatible with 'proper' C, but any C code that compiles both in a C++ and C compiler is actually also a (heavily outdated) subset of the C language (so for a C coder it takes extra effort to write C++ compatible C code, and it's not great because it's a throwback to the mid-90s, C++ compatible C is potentially less safe and harder to maintain).

For instance in C++ it's illegal to take the address of an 'adhoc-constructed' function argument, like:

    sum(&(bla_t){ .a = 1, .b = 2, .c = 3, .d = 4 });
(godbolt: https://www.godbolt.org/z/r7r5rPc6K)

Interestingly, Objective-C leaves its C subset alone, so it is always automatically compatible with the latest C features without requiring a new 'ObjC standard'.

Re: The C23 edition of Modern C

#202
post #65

Earlier quoted context omitted.

C++ can seamlessly include C89 headers. The C library headers for libraries I write often include C11/C99 stuff that is invalid in C++. Even when they are in C89, they are often incorrect to include without the include being in an `extern "C"`.

Yeah plenty of headers first have `#ifdef __cplusplus` and then they add `extern "C"`. And of course even then they have to avoid doing things unacceptable in C++ such as using "new" as the name of a variable. It takes a little bit of an effort to make a header work on C and C++. A lot less effort than making a single Python file work with Python 2 and 3.

The '#ifdef __cplusplus extern "C" { }' thing only removes C++ name mangling from exported symbols, it doesn't switch the C++ language into "C mode" (unfortunately).

Re: The C23 edition of Modern C

#203

Earlier quoted context omitted.

Because people choose to use pre-increment by default instead of post-increment? Why is that?

Why would you use post increment by default? The semantics are very particular. Only on very rare occasions I need post increment semantics. And in those cases I prefer to use a temporary to make the intent more clear

I rarely use pre-increment tbh, but post-increment all the time for array indices (since typically the array should be indexed with the value before the increment happens).

If the pre- or post-increment behaviour isn't actually needed, I prefer `x += 1` though.

Re: The C23 edition of Modern C

#204

Personally this[1] just makes C much more complicated for me, and I choose C when I want simplicity. If I want complicated, I would just pick C++ which I typically would never want. I would just pick Go (or Elixir if I want a server). "_BitInt(N)" is also ugly, reminds me of "_Bool" which is thankfully "bool" now. [1] guard, defer, auto, constexpr, nullptr (what is wrong with NULL?), etc. On top of that "constexpr" a…

auto is mostly useful when tinkering with type-generic macros, but shouldn't be used in regular code (e.g. please no 'almost always auto' madness like it was popular in the C++ world for a little while). Unfortunately there are also slight differences between compilers (IIRC Clang implements a C++ style auto, while GCC implements a C style auto, which has subtle differences for 'auto pointers' - not sure if those differences have been fixed in the meantime).

_BitInt(N) isn't typically used directly but typedef'ed to the width you need, e.g.

    typedef _BitInt(2) u2;
The 'ugly' _B syntax is needed because the combination of underscore followed by a capital letter is reserved in the C standard to avoid collisions with existing code for every little thing added to the language (same reason why it was called _Bool).

AFAIK defer didn't actually make it into C23?

I'm also more on the conservative side when it comes to adding features to the C standard, but IMHO each of the C23 additions makes sense.

Re: The C23 edition of Modern C

#205

Most important aspect of C is its portability. From small microcontrollers to almost any computing platform. I doubt that any new version of C will see that much adoption. If I want to live on cutting edge I would rather use C++2x or Rust rather than C. Am I missing something? What benefit this supposedly modern C offers?

One advantage of writing C code is that you don't have annoying discussions about what idiomatic code is supposed to look like, and what language subset is the right one ;)

For the cutting edge I would recommend Zig btw, much less language complexity than both modern C++ and Rust.

One good but less visible side effect of C23 is that it harmonizes more syntax with C++ (like ... = {} vs {0}) which makes it a bit less annoying for us C library maintainers to support the people how want to compile their C code with a C++ compiler.

Re: The C23 edition of Modern C

#206
post #132

Earlier quoted context omitted.

I care about performance, when it actually matters to acceptance testing. The less C the merrier. If you care about correct use of localisation, standard C and C++ libraries aren't really what you're looking for, or even C and C++ to start with.

C and C++ are the bedrock of operating systems with the best performance and extensive support for all languages. The only reason why iostreams are slow is because of its incompatible buffering scheme, and the fact that C and C++ need to stay in sync when linked together. And that brand of slow is still faster than other languages, except sometimes those that delegate i/o to pure C implementations.

Historical baggage, they weren't the first system programming languages, got lucky with UNIX's license allowing for widespread adoption, and won't be the last one standing either.

Re: The C23 edition of Modern C

#207

Earlier quoted context omitted.

I end up using a .S asm file with .incbin directives to embed files. #embed would be much nicer

Incbin works just fine from inline asm fwiw

Inline assembly isn't supported for x86-64 and ARM on MSVC which unfortunately also means the incbin trick can't be used there anymore.

Re: The C23 edition of Modern C

#208
post #161

Can someone link me to an article that explains why C is basically frozen at C99 for all practical purposes? Few projects worth talking about leverage features from C11 and newer

C99 is still new ! Microsoft tried to kill C by refusing to implement anything that wasn't also in C++. MSVC was 16 years late implementing C99, and implemented only the bare minimum. Their C11 implementation is only 11 years late. I suspect that decades of C being effectively frozen have caused the userbase to self-select to people who like C exactly the way it is (was), and don't mind supporting ancient junk compil…

Most of us liking a good language just did not use MSVC. I do not think many people who appreciate C's simplicity and stability would be happy with C++ / Rust. Zig is beautiful, but still limited in many ways and I would not use it outside of fun projects.

Re: The C23 edition of Modern C

#209
post #61

Earlier quoted context omitted.

Clang supports C11 - 23 in C++, as well as some future C features like fixed-point integers. The main pain points with Clang are just the fundamental differences like void* and char, which don't typically matter much at an interoperability layer.

There's a lot of subtle differences between 'proper' C and the C subset of C++, since C++ uses C++ semantics everywhere, even for its C subset. Many C++ coders are oblivious to those differences (myself included before I switched from 'mainly C++' to 'mainly C') because they think that the C subset of C++ is compatible with 'proper' C, but any C code that compiles both in a C++ and C compiler is actually also a (heav…

Because Objective-C initial proposal is that everything that isn't touched by Smalltalk like code, clearly in brackets or @annotarions, is plain C.

The pre-processor original compiler, before the GCC fork, would leave everything else alone, blindly copying into the generated C file.

Re: The C23 edition of Modern C

#210
post #105
post #71

Earlier quoted context omitted.

Right. Also it might it sound like array-to-pointer decay is forced onto the programmer. Instead, you can take the address of an array just fine without letting it decay. The type then preserves the length.

Nice, when you know the length at compile time, which is rarely from my experience. The holy grail is runtime access to the length, which means an array would have to be backed by something more elaborate.

Oh, it also work for runtime length:

https://godbolt.org/z/PnaWWcK9o

Post reply on HN