[HN Gopher] C meeting is over. C23 added:
___________________________________________________________________
C meeting is over. C23 added:
Author : ksec
Score : 186 points
Date : 2022-02-19 07:11 UTC (15 hours ago)
(HTM) web link (twitter.com)
(TXT) w3m dump (twitter.com)
| rwmj wrote:
| So true and false keywords are the only thing that has been
| added, or am I missing a part of this thread?
|
| Edit: I think one of these could be a better link:
| https://en.cppreference.com/w/c/23 http://www.open-
| std.org/jtc1/sc22/wg14/www/docs/n2864.pdf
| NotSoVeteran wrote:
| The linked tweet is the 4th in a sequence. If you scroll up you
| should see 3 more tweets with more info.
| [deleted]
| rwmj wrote:
| Thanks - Twitter UI is terrible.
|
| I'm glad the terrible "defer" suggestion didn't make it, but
| unfortunate that they didn't standardise the existing and
| widely used attribute cleanup.
| wartijn_ wrote:
| This is off topic, but I don't think the problem is just
| that the Twitter is terrible.
|
| If you want to link to a thread, you should click on the
| first tweet of that thread and copy its url. It's easy to
| see the rest of the thread: just scroll down.
|
| If you want to link to one tweet in a thread you should
| click on that tweet and copy its url.
|
| The person who posted the link to HN did the latter, while
| they should have done the former.
|
| Twitter could make it easier to see that a tweet is part of
| a thread though.
| notreallyserio wrote:
| While we're off topic here's my little rant about Twitter
| "threads":
|
| It's easy to see all of the tweets made by the author, at
| least those made as replies to themselves, but reading
| the actual threads is hard or impossible. At least I
| haven't figured out how to do it despite considerable
| effort.
|
| For example, say you want to view the replies to the
| tweet above the linked tweet, the one about "assert".
| There are supposedly 4 replies. If you tap that tweet you
| remain in the same list of self-replied tweets. There are
| replies at the end, but are they replies to the tweet you
| want to focus on? It doesn't look like it, but who knows,
| maybe? It's even worse on linger Twitter self-reply
| "threads".
|
| I don't know how Twitter's engineers got the well-
| established threading pattern so wrong. This behavior
| doesn't even increase the number of ads you see.
| secondcoming wrote:
| Twitter is bad if you don't have a twitter account. It'd
| be great if HN could change twitter links to go through
| nitter.net
| ksec wrote:
| I was so sure I copied the first tweet to submit. That is why
| the title is the same as the first tweet. Somehow I messed it
| up. May be Dang could change it to
|
| https://twitter.com/__phantomderp/status/1494801365297676293
| kevin_thibedeau wrote:
| They're still macros. C will never add new keywords outside the
| reserved namespace.
| duskwuff wrote:
| OR WILL THEY?!
|
| http://www.open-
| std.org/jtc1/sc22/wg21/docs/papers/2021/p231...
| fulafel wrote:
| The cppreference.com link says it removes "Representations for
| signed integers other than two's complement" - this could be
| pretty significant in making many previously implementation-
| defined programming patterns strictly conforming, but is it
| true? Doesn't seem mentioned in the Twitter thread.
| rwmj wrote:
| This is the accepted twos complement proposal:
| http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2412.pdf
|
| It seems like a sensible simplification to me. Is there any
| architecture that doesn't use twos complement (eg. uses
| separate sign bit + magnitude) and could run C code?
| qsort wrote:
| Some microcontrollers used to have saturating arithmetic,
| which is basically the only other behavior that makes any
| sense.
| MaxBarraclough wrote:
| Perhaps I'm missing something obvious, but isn't that
| orthogonal to representation? You could implement
| saturating arithmetic for any representation scheme, no?
| tomsmeding wrote:
| You can only observe whether the representation is
| 2s-complement or not if you can see what wrapping does.
| MaxBarraclough wrote:
| That doesn't sound right. You can use the union trick in
| C (but not C++, strictly speaking) to read the bit-
| pattern of a signed integer as an unsigned integer, for
| example. [0]
|
| Overflow of signed integer types remains undefined
| behaviour in both C and C++. A compiler is free to make a
| promise like _signed integer overflow is always handled
| with wrapping_ or _signed integer overflow is always
| handled with saturation_. (GCC has a flag, _-fwrapv_ , to
| enable guaranteed wrapping. [1])
|
| [0] https://stackoverflow.com/a/25664954/
|
| [1] https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-
| Options.html
| MaxBarraclough wrote:
| > Is there any architecture that doesn't use twos
| complement (eg. uses separate sign bit + magnitude) and
| could run C code?
|
| I think such machines are pretty much a thing of the past.
| This topic cropped up in a 2018 thread when C++ made the
| same change. [0]
|
| [0] https://news.ycombinator.com/item?id=17190864
| Findecanor wrote:
| The devil is not in the number representation but in the
| details. The proposal says:
|
| > Overflowing operations and out-of-range conversion are
| generally mapped to modulo operations and cannot trap or
| raise signals.
|
| This would be a problem on x86, where INT_MIN / -1 causes a
| #DE (divide error) exception. In C17 that is fine because
| signed integer overflow is undefined behaviour. But if the
| behaviour is defined, that trap would have to be caught or
| avoided.
|
| The best solution for performance would be to have a new
| trap handler. That would have to parse the instruction to
| find its length, and the divisor (in memory or register) to
| differentiate it from division by zero, write the constant
| result and remainder into the destination registers (always
| rax and rdx thankfully) and then continue with the next
| instruction.
|
| But I think this could be difficult to do in a fool-proof
| way, with how CPU exceptions are handled in different
| operating systems. Some operating systems might not even
| allow it at all.
| pascal_cuoq wrote:
| The sentence you quote is near to the words:
|
| "[The C++ standardization committee] WG21 has recently
| adapted the changes promoted in their document p12363.
| Generally, C++ goes much beyond what is presented here:"
|
| I would be extremely surprised if the proposal to make
| signed overflow defined behavior in C made it into C23.
| The window is narrowing and this would be a very big
| change to the language. Making it official that 2's
| complement is the only representation for signed integers
| is already a large change.
|
| Later in the decade, maybe.
| junon wrote:
| Having trouble figuring out if this is real. It sounds way too
| good to be true.
| Svetlitski wrote:
| "`typeof` is standard"
|
| Hallelujah, after only five decades generic, type-safe macros
| which evaluate their arguments exactly once will _finally_ be
| possible with standards-compliant C.
| saagarjha wrote:
| How so? You'd also need statement expressions for most of them.
| throwaway3neu94 wrote:
| No, you can use do{}while(0) usually. You only need statement
| expressions if you want it to evaluate to a value as well.
| CyberRabbi wrote:
| Whenever I use C I use it for the express purpose of supporting
| ancient platforms. These platforms often only support C89, so
| that's the dialect of C to which I restrict myself. If I am able
| to ignore those old platforms, I use C++. RAII is just so
| convenient.
| gefhfffh wrote:
| Have you evaluated Rust instead of C++?
| Koshkin wrote:
| Indeed, RAII and function overloading are the two things I
| sorely miss when I think of coding in C.
| beeforpork wrote:
| > Support for calling realloc() with zero size (the behavior
| becomes undefined)
|
| OMG! Please do not add _more_ undefined behaviour!
|
| We really need less UB, not more! What was wrong with
| 'implementation defined' as in C17? UB means that code that
| exists will now break if a new compiler decides that it can be
| smart. And we know how inventive this can get, right? Like
| removal of 'if(new_size==0) {...}' if the compiler can prove that
| 'new_size' went into 'realloc' before.
| c-linkage wrote:
| They'd better not convert that to undefined behavior!
|
| First, the specification for malloc() says you can call it with
| size 0 and it will still return a pointer to zero bytes; this
| means an array of bytes having size zero is legal.
|
| Second, having the compiler detect when realloc() is called
| with size zero changes what should be a library call into an
| intrinsic, whose very presence in the code is determined by the
| value of its arguments[0]. If you're going to do that you might
| as well just put exceptions in the language!
|
| [0] Most compilers assume UB "can't happen" and just remove the
| offending code altogether.
| masklinn wrote:
| > Most compilers assume UB "can't happen" and just remove the
| offending code altogether.
|
| To be clearer: UBs (specifically the assumption that they
| don't happen) get translated into constraints (since C's type
| system is extremely weak UBs are a very valuable source of
| such constraints to optimising compilers), those constraints
| are then propagated (forwards, and backwards, and upwards due
| to inlining) and any path for which the constraint does not
| hold can be considered dead.
| enedil wrote:
| Manual says
|
| > If size is 0, then malloc() returns either NULL, or a
| unique pointer value that can later be successfully passed to
| free().
|
| So it's not really an array of bytes of size 0.
| MichaelBurge wrote:
| What qualifies something as a "real" array of bytes?
|
| All RAM is an array of bytes, so any pointer to real
| memory(vs. virtual memory) is a pointer to an array of
| bytes.
| colanderman wrote:
| Where did you see this? I can't find it in the Twitter thread
| or any of the linked sources. I agree that "adding" support for
| something by making it UB makes no sense... as that generally
| would imply breaking forward-compatibility...
| beej71 wrote:
| Not only that, but the feature is genuinely useful.
| RcouF1uZ4gsC wrote:
| > typeof(...) is standard
|
| I thought C++11 went with decltype because typeof was implemented
| by compilers as an extension with various subtle semantic
| differences than what they wanted.
|
| I wonder why the C committee went with typeof instead of
| decltype?
| pwdisswordfish9 wrote:
| Because that would then create subtle incompatibilities with
| C++, stemming from the fact that C has no reference types.
|
| http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2927.htm#ex...
| [deleted]
| bonzini wrote:
| IIRC typeof is implemented in the same way by all compilers
| that have it, but it had some subtle differences with what the
| committee wanted. The differences presumably do not matter for
| C, in fact I think it was something related to references.
| vkazanov wrote:
| It's probably better to just follow the original WG14 Document
| log:
|
| http://www.open-std.org/jtc1/sc22/wg14/www/wg14_document_log...
| mojuba wrote:
| Removing K&R style function prototypes though is kind of big. I
| remember when one of the Objective-C upgrades started enforcing
| K&R. I don't think ObjC will be upgraded to C23 (ever, as it's a
| language being deprecated now I presume) so it will be stuck with
| K&R... while the rest will move on?
|
| Could someone also explain what this means for pure C in terms of
| compatibility? If there's void foo();
|
| would the meaning of it depend on which C standard is activated?
| plorkyeran wrote:
| Obj-C can be compiled using any version of C (and Obj-C++ can
| be compiled using any version of C++). You already can use C2x
| with obj-c if you desire. I don't know what "enforcing K&R"
| means in this context, but if you think that Obj-C requires
| using K&R-style function definitions you're very confused about
| something.
| flohofwoe wrote:
| IME ObjC (unlike C++) automatically supports the latest C
| standards, because ObjC just adds some syntax sugar on top of
| C, but otherwise doesn't 'mangle' its C subset into its own
| dialect like C++ does.
| dgrunwald wrote:
| What's being removed in C23 is the ancient K&R syntax for
| function definitions: int max(a, b)
| int a, b; { return a>b?a:b; }
|
| My understanding is that C23 does not change the meaning of
| function declarations. So "void foo();" remains a declaration
| of a function accepting an unknown number of parameters.
| zh3 wrote:
| Wow, that's annoying. There's a bunch of old code we have
| that'll need updating (written that way to keep the line
| lengths down).
| MawKKe wrote:
| ...can't you just configure your build system to compile
| those modules with pre-c23 standard?
| zh3 wrote:
| Of course. But one of the great things about C is that as
| a rule nothing breaks with compiler changes (as long as
| appropriate care has been taken) which this appears to
| violate.
| klyrs wrote:
| All the compilers I use have a default C version, and an
| optional flag to control which version to use. It's a non-
| issue.
| rightbyte wrote:
| Maybe the compiler will add a extension flag? I mean the
| K&R declarations still need to be supported in the compiler
| for earlier standards.
| mojuba wrote:
| According to the OP tweet though, `foo()` is now a function
| that takes no arguments.
| leetrout wrote:
| Agree the tweet makes it seem the behavior is changing.
|
| Edit: parent is correct it IS changing
|
| > We could make this change because foo() decls and
| definitions had been deprecated since C89/99, longer than
| I've been alive.
|
| > Implementations will likely warn on foo() decls for a
| while, and error if someone calls it with foo(too, many,
| args);.
|
| https://mobile.twitter.com/__phantomderp/status/14948125950
| 6...
| jesprenj wrote:
| Wouldn't int foo(void) be a function that takes no
| arguments and int foo() a function that takes an _unknown_
| number of arguments?
| suprjami wrote:
| Yes, that's the problem.
| suprjami wrote:
| That's a different thing. That's implied `foo(void)`.
| messe wrote:
| It WAS a different thing. That's changing in C23.
| zx2c4 wrote:
| Here's the document for that change: http://www.open-
| std.org/jtc1/sc22/wg14/www/docs/n2841.htm
|
| > In this proposal, a function declarator without a
| parameter list declares a prototype for a function that
| takes no parameters (like it does in C++).
|
| And it seems like gcc implements this under -std=c2x now:
| zx2c4@thinkpad /tmp $ cat a.c int blah() {
| return 7; } int main(int argc,
| char *argv[]) { return blah(argc);
| } zx2c4@thinkpad /tmp $ gcc -std=c17 a.c
| zx2c4@thinkpad /tmp $ gcc -std=c2x a.c a.c: In
| function 'main': a.c:8:16: error: too many
| arguments to function 'blah' 8 | return
| blah(argc); | ^~~~
| a.c:1:5: note: declared here 1 | int blah()
| | ^~~~
| duskwuff wrote:
| Which is much more consistent, IMO.
|
| int foo(int, int) is a function taking two arguments. int
| foo(int) is a function taking one argument. int foo() ought
| to mean a function taking no arguments, not a function with
| an unspecified number of arguments!
| pkrumins wrote:
| C is the only sane language left. It never changes and it lets us
| write code that just works. We can focus on getting things done
| and shipping rather than learning new features and Googling
| compiler errors. Learn once, ship forever.
| wffurr wrote:
| ...except it just changed.
|
| And you will be forever left writing insecure memory unsafe
| code.
| pkrumins wrote:
| One change per decade is not a change.
| zeckalpha wrote:
| More than once per decade: C11, C17, C23
| blinzy wrote:
| I guess you can say C17 is a change if you want to be
| pedantic except it didn't actually introduce any new
| features; it just corrected some defects found in C11.
|
| So we have C89, C99, C11, and C2X (C23?) as the only
| revisions introducing new stuff...
| phendrenad2 wrote:
| C99 is the last sane language left. The additions since then
| are just minor syntactic sugar.
| sys_64738 wrote:
| It's also upwardly compatible so no messing with code from a
| deprecated version. Python 2 to python three has this issue. If
| I need to change my code to make it run on the latest language
| standard then that is a big red flag for me.
| drran wrote:
| Majority of CVE's are because of C memory model, which is fixed
| in modern languages. C memory model is the constant source of
| vulnerabilities, thus it better to write new code in a memory
| safe language, like Rust.
| pkrumins wrote:
| Rust is a syntax error, not a programming language.
| moralestapia wrote:
| >Majority of CVE's are because of C memory model
|
| I haven't checked that but I believe you. My only nitpick is
| that I wouldn't put the whole blame for that on C, as there
| are proper ways to produce "safer"[1] code. What other
| languages did was lower the entry barrier to write better
| code, but that doesn't mean one language is inherently better
| that another.
|
| 1: No code is ever safe, not even formally verified code.
| phendrenad2 wrote:
| C and Rust have the same memory model though, unless you're
| using a definition of "memory model" that I'm unaware of.
| masklinn wrote:
| > Majority of CVE's are because of C memory model
|
| "Memory safety" (or lack thereof) is probably less ambiguous:
| usually "memory model" is the interaction between program and
| memory, specifically as it pertains to concurrency. And in
| the latter understanding I believe C has about the same model
| as C++, which is also the one adopted by Rust. And while it's
| fiddly, it's not a complete disaster.
| rightbyte wrote:
| Ye the churn is crazy in many languages. I almost had a heart
| attack when the twitter post stated that "true" and "false" are
| keywords in C23. However that seems incorrect.
|
| On my last workplace we argued if we dared to use stdint.h,
| since it was so new and fancy. I was a proponent, but there is
| something calm over discussing whether to use 23 year old
| additions or not.
| sys_64738 wrote:
| Does anybody bother about the stuff after C99?
| rossy wrote:
| MSVC just got C11 support a little over a year ago, so you
| won't see many big cross-platform projects using it yet,
| unfortunately. Some projects can optionally use C11 stdatomic.h
| and stdalign.h to replace old OS and compiler-specific
| extensions, but most of them still keep fallback code in case
| C11 isn't available.
| mprovost wrote:
| So does that mean we should expect C23 support in ~2033?
| pkrumins wrote:
| Nope.
| mungoman2 wrote:
| I can't tell if this is serious.
|
| Surely if you're still using C now it's for legacy reasons. And
| if using it for legacy reasons you are likely stuck using an old
| C standard.
|
| So who will use C23?
| rwmj wrote:
| Many things on a Linux system is written in C, and despite the
| noise on HN, developers who gets stuff done are constantly
| writing new code in C all the time.
| pjmlp wrote:
| Including plenty of new CVEs, we have to keep the security
| industry job market safe.
| rwmj wrote:
| Sure, I'm certainly not arguing that C is a good language.
| In RHEL we turn all warnings on, compile everything with
| hardening flags, use valgrind during development, and feed
| everything through Coverity.
| pjmlp wrote:
| The exception that confirms the rule.
| rossy wrote:
| The exception? It's standard practice for distros to
| compile with hardening flags, and if RH submits the bugs
| they find with Coverity upstream, that protects the 1000s
| of C projects they package.
| pjmlp wrote:
| Standard practice they say,
|
| https://googleprojectzero.blogspot.com/2021/12/this-
| shouldnt...
| torstenvl wrote:
| Mozilla is not a Linux distro.
|
| You have made dozens of negative (and sometimes rude)
| comments in this thread. I'm curious why you're spending
| so much time and energy being negative. If C isn't
| something you're interested in, why not just ignore it
| and move on?
| axiosgunnar wrote:
| > In RHEL we turn all warnings on, compile everything
| with hardening flags, use valgrind during development,
| and feed everything through Coverity.
|
| Surely the compile time is not 100ms anymore then?
| diegocg wrote:
| > developers who gets stuff done are constantly writing new
| code in C all the time.
|
| The amount of new C projects being created is falling at a
| fast rate. C isn't going anywhere, but it's certainly losing
| rapidly its prominence in the systems programming area.
| rwmj wrote:
| [citation needed]
| pjmlp wrote:
| You can start by C compilers nowadays written in C++,
| Arduino, AUTOSAR security standard, CUDA, DirectX, Metal,
| GoDot, Vulkan helper libs, SYSCL, ...
| phendrenad2 wrote:
| Those are just headlines, is there any evidence that
| those are actually overtaking C, and that the C++ used
| isn't just "C style C++"?
| [deleted]
| phendrenad2 wrote:
| I'll keep writing things in C, because it maximizes my
| productivity and gives me extra time to make it secure (less
| time than it would require to write it in Rust in the first
| place).
| dkjaudyeqooe wrote:
| C is a portable alternative to assembly language.
| pjmlp wrote:
| When the world is a PDP-11.
| nec4b wrote:
| And x86, Arm, PIC, Xtensa,... and everything else.
| pjmlp wrote:
| There is where you went off rails, with greetings from
| ACM.
|
| https://queue.acm.org/detail.cfm?id=3212479
| nec4b wrote:
| I'm so glad that you have linked this article from
| Chisnall. I can now ask you in what ways is the abstract
| model of a machine on which assembly language operates
| on, different from the one on which the C language
| operates on?
|
| This is the claim which started this thread:
|
| >>C is a portable alternative to assembly language.
| pjmlp wrote:
| C's abstract machine is leaky and full of surprises when
| UB comes into play for one.
|
| Second when people talk about C being portable Assembly,
| they mistakenly assume to know what comes out of the
| compiler's backend.
|
| Third, unless we are speaking about PDP-11 like CPUs,
| modern CPUs have tons of capabilities not exposed to ISO
| C.
|
| Finally, since 1958 there are portable alternatives to
| Assembly in systems programming with JOVIAL being one of
| the first remarkable ones, yet another thing that C did
| not invent.
| nec4b wrote:
| You haven't answered the question?
|
| Maybe because is there is no concernable difference
| between abstract machine models of both languages? You
| can't do anything more about instruction reordering or
| cache invalidation at the CPU level with assembly than
| you can with C.
| pjmlp wrote:
| You surely can, better read those CPU manuals about line
| bus controllers.
| nec4b wrote:
| Have you? I used to write device drivers mostly on ARM
| architectures and I have newer seen an instruction which
| would let me precisely control CPU instruction ordering
| or what it does with cache that I couldn't do in C.
| pjmlp wrote:
| That is why stuff like V-Tune exist with micro-ops
| profiler and pipeline debugging, maybe ARM should provide
| better tooling.
| nec4b wrote:
| This tool helps as much with C (or even higher level
| languages) as it does with Assembly. It doesn't change
| the fact both languages work on the same abstract machine
| model.
| pjmlp wrote:
| What is C's abstract model for NEON?
| nec4b wrote:
| A simple c library:
|
| https://github.com/projectNe10/Ne10
|
| You have not yet shown an argument for why c is not a
| portable assembly.
| kaba0 wrote:
| I don't see my SIMD instructions anywhere.
| jdkjs wrote:
| Here:
| https://www.intel.com/content/www/us/en/docs/intrinsics-
| guid...
| pjmlp wrote:
| That isn't C, rather Intel C.
| nec4b wrote:
| The word "portable" means a subset of everything possible.
| Do you think every CPU architecture supports SIMD?
| foxfluff wrote:
| > The word "portable" means a subset of everything
| possible.
|
| Exactly; for example, C has single precision and double
| double precision floating point, 64 bit types, and
| complex arithmetic because every CPU architecture has
| those built-in.
| nec4b wrote:
| No, but those things can be easily emulated on every
| hardware or simply not used. One more reason to use C
| instead of plain assembly.
| pornel wrote:
| Where's my overflow flag?
| nec4b wrote:
| Not all CPU's have overflow flags. On those that have them,
| you can also usually access them in C in a non portable
| way.
| uecker wrote:
| C23 will get support for checked integer operations that
| report overflow.
| brian_cloutier wrote:
| At a previous employer of mine we would have happily switched
| to c23. Postgres is written in c and if you want to write an
| extension for Postgres you're going to have the easiest time if
| your extension is also written in c. However, there's no reason
| not to use the newest c version.
|
| So, c is not just for legacy code.
| DyslexicAtheist wrote:
| _> So who will use C23_
|
| I can't say if I'd immediately jump to C23 but I'll be thrilled
| to give it a try.
|
| Currently I'm rewriting an entire automotive OCPP charging
| point and it's associated CSMS in C because the original dev
| (who has no experience with Edge/IoT and just Cloud/SaaS)
| thought it was a great idea to implement this in golang. The
| binary size alone is already a problem where all I have is 30MB
| (needs to be shared with logs, sqlite, and 2 another "user-
| space" application).
|
| I could have chosen Rust/Zig/Nim (I really wanted to) but the
| client rejected it for very good reasons that have nothing to
| do with type-safety/performance/security but are all about
| good-business practice and risk management:
|
| - when I leave in a few weeks, there are plenty engineers
| inside the company who can maintain the system.
|
| - the domain is quite niche so to understand their solutions
| and requirements you can't do away without an occasional trip
| to their office. the client is not in a capital city with a
| vibrant tech-scene and weekly meet-ups and lacks the talent-
| pool.
|
| The constraints by the market (scarcity) makes Rust/Nim/Zig (my
| personal front-runners) very risky tools.
|
| C++ could have been an option but it's total overkill because
| most of the components you need to build this (websocket, mqtt,
| http, sqlite, zlib, openssl, ...) are anyway implemented in C
| and I actually don't want things like exceptions or templates
| in this _at all_ for performance reasons.
|
| If you split your OS into layers from HW (ring-0) all the way
| to layer-5 (process management e.g. systemd etc) then 99% is
| still written in C. So your argument throws every layer under
| the bus except user-land (L-6).
|
| C isn't going away only because of embedded/IoT. It's going to
| stay because choosing a language is like the "3 most important
| rules in real-estate: location. location. location".
|
| The language is your location and your primary lock-in factor
| for your solution/business. Once you've decided on language the
| only way to change this is an entire re-write. Even if you
| rewrite you still have to consider culture and available
| resources that must be in place long before you chose the
| programming language. And keep in mind the people who all took
| stakes in the original implementation and must all be sold on
| the idea that whatever new replaces the old "is sooo much
| better". That's not an engineering problem but a power/people
| problem.
|
| Edit: So just because "the engineer inside of me" wants to use
| Rust/Nim/Zig or whatever new to satisfy my intellectual
| curiosity is not enough reason. In fact my potential inability
| to see beyond that is a good reason for them to be very very
| careful about what advise I give.
| WithinReason wrote:
| Is it a good summary that the only reason for deciding for C
| instead of Rust/Nim/Zig is that not enough programmers know
| Rust/Nim/Zig?
| DyslexicAtheist wrote:
| imo not the only reason but it's the most cited one by
| those who give me a budget and limit my freedom to use the
| tool I personally think is right for the job. just because
| I can sell an engineering audience on my (IMHO correct but
| artisanal) views doesn't mean it's what is best for the
| business.
|
| Because they know the moment they come back "crying" saying
| "we can't find anyone with these skills" I'll consider it
| as their problem, because I for sure am not going to help
| sifting through LinkedIn profiles or get involved with
| their "talent acquisition strategy" (at least not in the
| capacity of an architect/engineer)
|
| I'm not saying always use C but if you have a very narrow
| skill-set in your team then switching languages is a long-
| term strategic decision that goes well beyond the opinion
| of the SW-teams. It's about strategy, budget, risk. That's
| probably true for most new languages / tools that replace
| the status-quo and not just about C vs Rust&Co. If I bring
| in a new technology then I'd first use them in parts of the
| system that aren't core-business (e.g. my infra automation
| etc) and then gain experience slowly with them before
| considering allowing them into parts that make up my core-
| business. It's a long term project to adapt a new
| technology not something a few devs decide. (start-ups
| switching from MVP to real products might be an exception,
| as are bigger companies switching from PoC to a real
| implementation, etc.)
| WithinReason wrote:
| Well then "legacy reasons" cited by GGGP was actually
| right. That's what I was wondering as well.
| blinzy wrote:
| From my personal experience, at work we use C and not Rust
| because for really low-level code (e.g., kernel bypass,
| niche datastructures, real-time, etc.) I believe Rust would
| have to use "unsafe" due to work with raw pointers and
| other code that can't be easily, or at all, expressed
| otherwise. In such a scenario a lot of the advantages Rust
| supposedly brings are diminished or gone.
|
| When that happens, considering that our company's
| knowledge/experience with C (or C++, although not my case)
| is vastly deeper than with Rust it makes no sense to choose
| it for any of that type of code we write, old or new.
|
| Zig looks promising but it's still too soon to take any
| risk in adopting it; in 5 years time it may be worth
| revisiting it and see how it has matured...
|
| Finally, software we may write but that gives us no
| competitive advantage over other businesses, sure that can
| be in Rust, Go, Java, Python, whatever.
| foxfluff wrote:
| I will continue to use C because I haven't seen an appealing
| alternative.
| 10x-dev wrote:
| C is the best choice if you want _all_ of: small (both language
| and binaries), fast (both compiler and binaries), obvious (no
| /minimal complex magic), close to the metal, with excellent
| debugging support, portability and integrations.
|
| No other language has been battle tested for longer and more
| extensively than C.
|
| Your kernels, OSes, drivers, databases, web servers and
| compilers are written in C.
|
| If some of these features are not important to you, there are
| hundreds of slower, more complex and less portable languages to
| choose from, that provide other benefits instead, such as more
| convenience, more correctness and higher level abstractions.
| kaba0 wrote:
| C isn't _that_ small, compare it to a Zig hello world. Fast
| is relative -- due to C not having good expressive
| /abstracting powers, it will leave you to inferior solutions,
| eg. counting string length multiple times at call sites, vs
| C++'s small string optimization, which is simply not possible
| in a user-ergonomic way in C. Regarding obviousness, I would
| add UB here, so Zig for example would beat it.
|
| C is not any closer to the metal than other system level
| programming languages, this myth should just die. Your code
| at -O3 gets mangled to oblivion, unless you are a compiler
| writer of the respective compiler, you will have no idea on
| the generated code. This is the exact same as with C++, Rust,
| etc, hell, C doesn't have proper simd support, so in a way
| the former two is closer to the metal.
|
| But I do agree on portability and integrations - so C will
| not die, but I really have a hard time seeing why should I
| choose C over any of the listed languages, unless I target
| some obscure CPU architecture.
| moralestapia wrote:
| >due to C not having good expressive/abstracting powers
|
| I disagree, if anything, C's scantness forces you to
| abstract things much properly, unless you plan to write
| pages of boilerplate code here and there.
| kaba0 wrote:
| With all due respect - how do you write a string library
| in C then? Char* is not one.
| dzaima wrote:
| In C it's possible (and, to some level, very much
| encouraged) to write your own things to replace whatever
| built in thing you don't like for whatever reason, be it
| speed, size, portability.
|
| C not having fancy built-in structures means programmers
| are more careful about choosing simple ones, which
| dramatically cuts down the amount of completely pointless
| generated code. -O3 can optimize registers and maybe memory
| reads/writes, but it can't remove reallocation from each
| call to a vector push, remove a reference count from a
| whole object type, or do pretty much anything with any
| moderately complex heap data structure. Sure, that comes at
| the cost of more advanced things being horrible to write,
| but it's a trade-off.
|
| And I'll just disagree that UB must be unobvious. To me,
| it's one of the most useful optimization tools. You can
| check for it with sanitizers, and explicitly invoke it to
| convey information about hidden behavior to a compiler.
| It's not magic.
| kaba0 wrote:
| > C not having fancy built-in structures means
| programmers are more careful about choosing simple ones
|
| Resulting in linked lists everywhere which have pretty
| terrible performance characteristics. You should be
| worried about those way before the occasional vector push
| reallocation cause you any problem. (And you can specify
| initial capacity so there is that)
| dzaima wrote:
| linked lists - true, but at least when you write them
| you'll be certain of what they do, and, coupled with
| knowledge of cache performance, precisely how bad they
| are. About reallocation I don't even mean the copying,
| but just the code needing to check for the chance
| overflow on every push. Besides the obvious waste of
| instructions to check for that, it also clobbers
| registers even if the branch isn't taken, and thus will
| easily result in a lot more unnecessary spilling to the
| stack. This kind of pointless thing happens in a ton of
| data structures.
| kaba0 wrote:
| Branch prediction exists so the common case can be made
| very fast (much faster than jump to this remote pointer),
| and also, rust uses an optimizing compiler for a reason.
| Eg., you use a vector inside a for, the vector's code can
| be inlined and the checking part be done only at the
| boundary. Also, one can also manually perform an
| unchecked push/get/whatever as well.
| dzaima wrote:
| The common case may be fast, but it's still slower than
| not having a rare case in the first place. The untaken
| branch will still affect register allocation (out of the
| ~15 x86-64 general-purpose registers, only 5 (6 if you
| count rbp) preserve data after a non-inlined function
| call in the System-V ABI (of which there will be at least
| one, ending in malloc somewhere), and the compiler has to
| accommodate both taken and untaken at the branch end) and
| will eliminate any hope of SIMD vectorization, among
| other wrecked optimizations.
|
| Unchecked operations are acceptable if your code has a
| single hot loop, but if you have a hundred small
| functions, each taking 1% of the time, you probably won't
| carefully examine every stdlib function each of them uses
| and write code to "work around" every unnecessary thing
| the stdlib does.
|
| Yes, that's a ton of micro-optimization, but micro-
| optimization can bring a ton of speedup, so I'll take
| whatever makes it simpler (or not needed in the case
| where you already know what will happen due to having
| written it)
| kaba0 wrote:
| Feel free to wrap it into a repr(transparent) type which
| exposes the unsafe operations by default.
|
| But I seriously doubt that programs would benefit much
| from these micro-optimizations - there are rare and
| unfortunate cases where indeed there is no one single
| bottleneck for a program and thus there is no simple way
| to improve performance, but the vast majority of programs
| spend all their life in a tight hot loop, and anything
| else doesn't matter in the slightest - hell, as mentioned
| C gets away with as many linked data structure as they
| want, but writing those in goddamn bash would suffice as
| well.
| 10x-dev wrote:
| Are you going to mix all those languages into one project
| and somehow use their advantages but steer away from their
| disadvantages?
|
| Sure, other languages have caught up or have improved on
| some of the features where C shines.
|
| Let's remove portability and integration from the feature
| list, because that's strongly related to C's tenure.
|
| Which _one_ of the languages you listed matches the rest of
| the feature set I brought up? * Small
| language * Fast compile times * Fast binaries
| * Small binaries * Great debugging experience *
| Close to the metal
|
| In my opinion, they all fail in at least one category, and
| that's expected - additional functionality can't come for
| free. You can only accept its cost.
| xigoi wrote:
| Zig? I personally haven't used it, but based on what I've
| heard about it, it fulfills these criteria.
| chaz72 wrote:
| That's what I am betting on - but it isn't 1.0 yet, and
| that matters too.
| foxfluff wrote:
| And they fail in other categories too, e.g. C can be very
| terse whereas most modern so-called replacements tend
| towards verbose. For me that's a development exactly in
| the wrong direction; I'd rather have a more terse C.
| mprovost wrote:
| C certainly has been battle tested but I wouldn't say that it
| passed with flying colours. Every one of the examples that
| you cite has had bugs/crashes/vulnerabilities that would have
| been avoided with newer languages.
| WithinReason wrote:
| Languages exist that compile to C which gives them many of
| the above advantages and more, so why choose C over them?
| 10x-dev wrote:
| Control over the code that actually runs.
|
| We already lose quite a bit of control with C (e.g. it
| reorders your code as it pleases) to gain portability
| across CPUs, otherwise we'd have to rewrite the code in
| several assembly languages.
|
| If you consciously choose to give up even more control over
| the code that runs (because a compiler that targets C
| necessarily adds another layer of autogenerated code that
| you don't control) then it better be a wise tradeoff.
| WithinReason wrote:
| The downside of reordering being performance? Or
| something else?
| 10x-dev wrote:
| Performance is usually the upside. The downside is subtle
| bugs that can happen due to side effects of the
| statements being reordered between sequence points.
| WithinReason wrote:
| AFAIK compilers don't reorder if it would change the
| result.
| Thiez wrote:
| Compilers not allowed to violate the language spec when
| optimizing. But the spec may be fairly generous in its
| allowed interpretations, which may not match what a
| programmer may naively expect. C, with its _many_
| undefined behaviors and implementation defined behaviors,
| is especially dangerous.
| dig1 wrote:
| Depending on transpiler (compilers that will compile to C),
| you can get near representation in C (rarely) or something
| completely different (frequently). In Scheme/LISP world
| (where transpilers were popular for a while), even a simple
| expression like "(+ 1 1)" will rarely give you something
| like: "int a = 1 + 1;". I've seen these things would
| produce dozen of lines of various boxing/unboxing calls,
| type checks and GC protection marks. If the compiler is
| really aggressive, it will just put "2" as a constant.
|
| I think that the only benefit of "compiling to C" was
| reusing existing compilers, not tooling around it. Also,
| debugging that code is a nightmare unless you are intimate
| with transpiler internals.
| sys_64738 wrote:
| A compiler that translates to another language used to be
| called a translator.
| zabzonk wrote:
| All compilers covert programs in one language (say C)
| into another, (say assembler or machine code), and they
| are called compilers. The whole transpiler thing is a bit
| bogus, but a C compiler has never IME been called a
| translator.
| raptorfactor wrote:
| Having never used such a language, I'm curious, what's the
| debugging experience like? Can I source level step the
| application in the original language or do I have to debug
| the generated C?
| TingPing wrote:
| It is always a pain to debug transpiled C IME.
| rightbyte wrote:
| You can put in line pragmas for e.g. gcc that will point
| you from "foo.gen.c" to "foo.fancylang". However it is
| not very useful unless the fancy language matches C's
| structs and native types and also does not mangle names.
| rwmj wrote:
| One of the criteria is "excellent debugging support" which
| you don't get with transpiled languages, since you'll be
| buried in generated code when you open the debugger.
| pjmlp wrote:
| Languages like Eiffel prove this isn't the case, it is a
| matter of proper debug tooling.
| zabzonk wrote:
| Of course, Eiffel is such a popular and widely used
| language, with a great toolset. /s
| pjmlp wrote:
| The amount of users doesn't change the fact of the
| tooling quality, but no wonder, UNIX folks tend to only
| take free beer, so what do they know about fine wine.
| zabzonk wrote:
| I've read the Eiffel books, and tried to use the Eifell
| tools, on Windows - a horrid experience. I am not a "UNIX
| folk" and I can't imagine what comparing UNIX and Eifell
| has to do with anything. It is basically an unuseable
| programming language and toolset, promoted by an
| egomaniac with a grudge against C++.
|
| If you disagree, please provide a link to something
| medium sized and useful written in Eifel.
| pjmlp wrote:
| Useful to whom?
|
| To you or the companies that keep Eiffel Software in
| business for 30 years?
| zabzonk wrote:
| > the companies that keep Eiffel Software in business for
| 30 years?
|
| Such as? If you can't provide links to people using
| Eiffel succefuly, then maybe there are none.
| xigoi wrote:
| shakna wrote:
| How many of your preferred programming languages are written in
| C?
|
| Yes, many self-host, but a considerable number of them don't
| want the complications that can bring.
| pjmlp wrote:
| Modern C compilers are written in C++.
|
| So much for C's simplicity in writing compilers.
| shakna wrote:
| Yes, C can be simple for writing a compiler. [0][1]
|
| No, optimisation, on the other hand, is not a simple
| problem.
|
| [0] https://github.com/rui314/8cc
|
| [1] https://github.com/rui314/chibicc
| pjmlp wrote:
| Naturally it can be simple, it was already a basic
| language when compared with what 1960's have produced.
|
| The evolution of Bootstrapping CPL compiler + a set of
| basic types.
| uecker wrote:
| There are plenty of C compilers written in C. Large
| compiler suites for C/C++ are usually written in C++. But
| as a contributor to GCC, I can say that large parts of the
| code still look very much like C.
| pjmlp wrote:
| Plenty of compilers... right.
|
| If you cannot compile GCC with a C compiler, it isn't C.
| uecker wrote:
| There a couple of open source C compilers TCC, SDCC,
| tendra, chibicc, ACK, LCC, PCC, etc. and also many
| commercial ones.
|
| It is true that GCC is not written in C anymore, but it
| is easy to see that the code is still relatively close. I
| am also myself writing a C compiler in C at the moment
| and there is no problem at all.
| jonp888 wrote:
| There are many many people out there using C for embedded
| software.
| mkl95 wrote:
| There are tons of CPython users AKA Python's default
| implementation... the software world is full of high level
| abstractions built on top of C.
| sam_bristow wrote:
| The problem is that embedded compilers are not known for
| keeping up with the standards. The only hope is that the
| moves to GCC and Clang continue.
| bsder wrote:
| gcc (thankfully) is the default (you download gcc compiled
| for ARM directly from ARM itself) for ARM embedded so when
| gcc gets it, ARM gets it.
|
| So, presumably, RISC-V will also get it at the same time.
| pkrumins wrote:
| No one cares about the standards. We only care about
| getting things done by writing regular C code that works.
| uncomputation wrote:
| Huh? What do you think defines "regular C code that
| works"? Standards.
|
| Every compiler you have used operates at a bare minimum
| on the C standard. That's why they are often advertised
| (if not GCC/Clang which are assumed to be up to date) as
| "C(89|99|11|17) compliant." "Code that works" is code
| which is operates under constraints and guarantees
| specified by a standard, anything else is undefined or
| unportable.
| xigoi wrote:
| I'll rather have code that runs on an actual computer
| than code that should hypothetically run according to a
| long document that costs 60 dollars to read.
| pkrumins wrote:
| Only the standards people care about standards. We
| (programmers) want to just get things done. We don't care
| about the standards. No one reads the standards. Also no
| one cares about portability. All computers have been the
| same for the last 20 years.
| pjmlp wrote:
| Right, then comes the day another OS or CPU needs to be
| supported and some clever developers learn their lesson
| about language standards during a couple of late nights
| tracking down production issues.
| drran wrote:
| We, developers, care about standards, because we want to
| get things done once.
| flyinglizard wrote:
| Embedded environments are specific and esoteric enough
| that compiler portability is the least of your concern
| when migrating code from one platform to the other.
| kstenerud wrote:
| I will.
|
| C is everywhere and is not going away (it's #2 on TIOBE and on
| the rise again). Now that fewer people are learning it, I get
| more juicy contracts.
| reassembled wrote:
| I feel like there's actually a growing subculture of C
| programmers of late, seemingly spawned by Casey Muratori's
| Handmade Hero series, Zed Shaw's "Learn C The Hard" way and
| other more recent popularizations of C and low level
| programming ideas. There's a whole "Handmade" software scene
| growing up, seemingly as a reaction against the bloat and
| over engineering of more recent software trends like Electron
| and web apps. Just the other day I stumbled across a vibrant
| Discord group focused on a fairly new but surprisingly
| feature complete game engine called Gunslinger, written
| entirely in C99. I've been working on my own C-based game
| engine for awhile too after having been exposed to the ideas
| of Handmade Hero, as well as from the influence of a good
| friend who has been writing games in C for many years. He's
| now working on an application called Pixel CNC for generating
| 3D tool paths from 2D images.
| saagarjha wrote:
| > seemingly spawned by Casey Muratori's Handmade Hero
| series, Zed Shaw's "Learn C The Hard" way
|
| It's kind of unfortunately, really, because both authors
| have very skewed viewpoints of C that are arguably quite
| incorrect.
| edflsafoiewq wrote:
| What viewpoints are those, for those of us unfamiliar?
| saagarjha wrote:
| Zed Shaw doesn't really like C because it lets you shoot
| yourself in the foot. This is an OK opinion to have, but
| then he goes and writes books about C that basically talk
| about how the language is bad (ok, I guess?) but the then
| claims he has solutions to these problems, without
| understanding that the problems he has with C are not
| solvable within the language (for example, when handed an
| arbitrary pointer, there is _no way_ to tell whether it
| is valid).
|
| Casey Muratori is fundamentally at odds with how
| undefined behavior works in C and has opinions(tm) on how
| to fix the language to make things work the way he wants
| them to, when in reality he just probably wants another
| language.
| throwaway2214 wrote:
| also arguably quite correct
| Didah wrote:
| Out of curiosity: why do you consider Casey's viewpoint
| incorrect?
| saagarjha wrote:
| Casey doesn't really understand how optimizing compilers
| work, so he likes to talk about how they keep breaking
| his code and that they should just run the optimizations
| that won't do that.
| plafl wrote:
| C++ requires to devote your life to it but you can learn C
| and spend a year using it and suddenly you have a dangerous
| but powerful tool in your toolbox forever.
| gefhfffh wrote:
| It's not like C++ is always the only alternative, see
| e.g. Rust which is way simpler
| lumb63 wrote:
| I agree that Rust is simpler than C++ (in some ways), but
| I'd say it is far more complex than C.
| Thiez wrote:
| That depends on how you define complexity. It is far
| easier to write a working program without memory leaks,
| various types of vulnerabilities, and undefined behavior
| in Rust than it is in C.
| phendrenad2 wrote:
| It depends on what level of security you need. If you're
| writing a 3D game engine, a minor memory leak probably
| isn't worth the extra time required to write it in Rust.
| Even if you're writing a kernel, fuzzing and formal
| verification can get you 99.999 of the way to the
| guarantees of Rust.
| pornel wrote:
| C is probably still popular, but TIOBE is less accurate than
| a horoscope.
|
| TIOBE index shows C has lost 62% of its users in 2016-2018,
| then almost tripled in popularity next year, and then again
| lost almost half of its users.
|
| Do you think such swing of popularity is possible for such an
| established slow-moving language? I don't think so -- it just
| shows how far TIOBE can diverge from reality, and that the
| error bars on the index should be +/- 50%. A few % blip means
| nothing. TIOBE is measuring rollouts of new Google search
| algorithms, not language popularity.
| aardvark179 wrote:
| Huge amounts of software are "legacy" but built with perfectly
| modern tool chains and will support c23 just fine. Even for
| large bits of software which have been mostly rewritten you'll
| often find core libraries that are still actively developed but
| have never been ported away from C.
| pkrumins wrote:
| We all use C because it works and we love to get things done.
| drran wrote:
| Not all of us use C, because it's very easy to create
| security holes in C. For example, web browsers are using slow
| JavaScript just because it memory safe.
| sgt wrote:
| Sounds like you're not really in touch with the real word. C
| has many benefits and it is super practical. Yes, you can write
| unsafe code, but safety isn't always your #1 priority. There
| are also tools you can use to identify issues, which will
| mitigate risks.
| Koshkin wrote:
| The truth is, C is merely a historical artifact, one step
| above the PDP-11 assembly, created in order to make the UNIX
| source code portable. It has transcended its original
| purpose, and with it being elegant and simple as it is, I
| would still never trust it to run a pacemaker.
| KnobbleMcKnees wrote:
| I'm really starting to believe that there's a cohort of
| modern programmers that only see programming languages in
| terms of the high level syntactical features they provide.
|
| The logic of it is something like: I write the code, I run a
| command written using similar code, scenes deleted, my
| program runs and my IDE tells me if there are problems in my
| code.
|
| This is sometimes defined as the difference between
| developers and engineers, but I don't really buy the analogy
| because they're mostly highly competent and able to build
| solid and principled architecture into their software.
|
| This is the only reason I can summise that educated
| programmers would say something like C is irrelevant.
|
| I guess not everyone needs to have a depth of understanding
| of the platforms that underly their languages of choice, but
| - as demonstrated here - it certainly doesn't inform the
| future of languages when they are inherently tied to their
| ability to integrate with different hardware and OSs.
| pjmlp wrote:
| It was already irrelevant when using MS-DOS with Turbo
| Pascal/Modula-2/Basic compilers, or Mac OS (originally
| written in Object Pascal/Assembly).
|
| It was UNIX industry adoption, followed by GNU Manifesto
| that made to more relevant than it should ever have been.
| tpoacher wrote:
| For all of us that follow an "I do not want to log in to twitter"
| philosophy, can someone here please post an alternative link?
|
| Incidentally, I'm glad Twitter now blocks you from reading if not
| signed in. I'm hoping this will encourage the use of
| alternatives.
| sva_ wrote:
| I'm not signed in and read it fine. My uBlock filters are
| twitter.com##[id^="layers"] >
| [class^="css-"]:has([dir^="auto"]):not(:has([aria-
| expanded])):has(a[href^="/"]):has-text(/Log in|Sign Up/)
| twitter.com##html[dir]:style(overflow: auto !important;)
| sebow wrote:
| There is indeed nitter.I also recommend using an extension for
| general redirecting.A popular one I use with presets for big
| sites is Privacy Redirect (ff) but there are also ones for that
| allow customization (Redirector for example, also ff).
| deadmercury wrote:
| Use nitter.net
|
| https://nitter.net/__phantomderp/status/1494884135688626180
| sys_64738 wrote:
| It used to be that every new language starts off with a
| translator to C. Not sure if that's the case nowadays.
| dragonwriter wrote:
| > It used to be that every new language starts off with a
| translator to C.
|
| No, it really never was that way, though there were some
| languages (especially ones that started as C plus some
| additional features, like C++ and Obj-C) that did that.
| qayxc wrote:
| With the advent of LLVM that's not common anymore.
|
| Bootstrapping can be done in pretty much any language nowadays.
| pjmlp wrote:
| Neither it was common before, Objective-C, C++, Eiffel are
| probably the only known ones with mainstream market share
| that actually went via the compile to C as initial
| implementation.
| pjmlp wrote:
| Not really, some did follow that path.
| cpeterso wrote:
| Another nice convenience: a new _#elifdef_ preprocessor directive
| to replace longhand _#elif defined()_.
|
| https://en.cppreference.com/w/c/23
| pjmlp wrote:
| Finally C catches up with Algol 60 boolean types, it only took 60
| years.
|
| Maybe in another 60 it will get proper strings and arrays.
| moralestapia wrote:
| >Maybe in another 60 it will get proper strings and arrays.
|
| If you think this is missing, there's a big chance you don't
| "get" C.
|
| Also, if you don't know how to properly emulate strings in a
| safe way in C nowadays (for which plenty of code sample and
| librariesexist), your skills with the language are quite poor.
| mhh__ wrote:
| Adding so-called fat pointers to C that could be bounds
| checked would probably instantly eliminate a large fraction
| of _all_ security issues.
|
| Of course, you can emulate these yourself, it's just a struct
| but not everyone does.
| Findecanor wrote:
| C99 introduced variable-length array _parameters_ and
| variable-length array _pointers_ together with variable-
| length arrays (VLA). These take another parameter or
| variable as a length-parameter. These became optional in
| C11 together with VLAs (for some reason) but are supposed
| to again become mandatory in C23. However (yet, for some
| reason) the pointers can (in the latest published draft,
| still) only be inside procedures: not in structs or in
| global variables.
|
| I think it would not be impossible for a C compiler to
| detect and produce a warning if an index used with such an
| array-pointer is not checked against the array-pointer's
| length variable.
|
| This would not make bounds-checks automatic, but the use of
| these types could make compilers point out when bounds are
| not checked or checked incorrectly.
| flohofwoe wrote:
| Adding opaque builtin struct types to C would be kind of a
| big deal though and would probably creep into other parts
| of the language and interact with them in unexpected ways.
| Features like fat pointers, slices, builtin dynamic
| arrays/strings or tagged unions would all require builtin
| opaque structs. This would be a whole different language
| (closer to Zig).
| mhh__ wrote:
| It really wouldn't be that hard to do. The syntax would
| be trivial, and the whole point is that you want it to
| creep so people actually use them.
|
| There's no overhead to doing it, but you save a bunch of
| bugs earlier, all for stopping conflating arrays with
| pointers, which is something not much code does these
| days anyway
| pjmlp wrote:
| I surely get C, having to deal with its casualties in
| DevSecOps.
|
| I have been "getting" C since 1992, across Xenix, DG/UX, HP-
| UX, Solaris, AIX, FreeBSD, Linux, Amiga, Windows 3.x,.....
| moralestapia wrote:
| Well, then, you must know it's not really a big deal to
| write code with proper memory checks.
| dnautics wrote:
| It's a big deal, you need about 1/3 of sel4 proofs
| pjmlp wrote:
| I have found yet another C expert.
|
| https://www.cvedetails.com/vulnerability-
| list/opmemc-1/memor...
| coldtea wrote:
| If you think that, then you really don't get C - not as
| in "it's intents", but as in its actual history and
| repurcursions...
| nec4b wrote:
| You once claimed C requires UNIX like OS to run.
| coldtea wrote:
| And he was right. He didn't mean it as a statement of
| fact (which would be wrong, and he already knew it).
| nec4b wrote:
| No he was definitely wrong. Ask any C developer.
|
| His comment:
| https://news.ycombinator.com/item?id=20828974
| pjmlp wrote:
| I claim it yet again on this very comment.
|
| Without UNIX spreading with its free beer into
| universities, C would have been a footnote on the history
| of system programming languages.
| nec4b wrote:
| Nope in the above comment you claim something else.
|
| Here is where you claim C requires UNIX like OS:
|
| https://news.ycombinator.com/item?id=20828974
|
| Let me tell you, in embedded development we run C on bare
| metal or under RTOS. There is no UNIX in sight. And the
| code is portable to many CPU architectures.
| pjmlp wrote:
| A snowflake RTOS without POSIX, call me amazed.
| nec4b wrote:
| I'm happy you learned something.
| tialaramex wrote:
| Much more importantly, without UNIX and free beer TCP/IP
| there's a fair chance the Internet isn't the Network and
| none of this (gestures at HN and the Web) happens. That's
| a much bigger impact than C which is just a programming
| language, even if you count the influence of NUL-
| terminated strings, and all the semi-colon languages
| (including even Javascript and Rust, which are very
| different from C but preserve the enthusiasm for semi-
| colons) the Internet as Network makes more difference.
|
| In particular it's possible X.25 could have won. JANET
| (the tertiary education network in the United Kingdom)
| was exclusively doing X.25 until 1991, when it tries an
| experiment offering IP. Unsurprisingly free beer TCP/IP
| offers a cornucopia of interesting new toys and sites are
| very enthusiastic about JIPS (the experimental IP
| service) so that by 1992 the IP service is no longer an
| experiment but the primary service, with X.25 maintained
| only until 1997.
|
| You do get the Network anyway of course, that's what
| everything is leading up to after Shannon, but you
| probably get an X.25 flavoured Network instead of the
| Internet, or some other system coming from another
| direction, and broad deployment might have been delayed
| into the early 21st century rather than the 1990s
| depending on exactly how things work out. Stallman's GNU
| project doesn't happen, Tim's toy hypermedia system
| either doesn't exist or is a small inconsequential
| experiment largely unknown outside hypermedia fanatics,
| and Linus Torvalds probably doesn't make an operating
| system kernel for his 386 microcomputer. It's a very
| different environment, C is small potatoes by comparison.
| nec4b wrote:
| C must be really amazing compared to Algol than. It powers
| today's computing infrastructure without having proper boolean
| type. Are there any widely used applications written in Algol?
| bitwize wrote:
| The Burroughs MCP operating system and some applications
| written on top of that. In fact, I believe that was the very
| first OS to be written entirely in a high-level language.
|
| MCP is not today widely used in the same way, say, React or
| Linux is, but businesses used and depend on it such that it's
| still sold and supported, as Unisys ClearPath MCP.
| User23 wrote:
| I've heard that Burroughs had an absolutely world class
| engineering team in their heyday.
| pjmlp wrote:
| UNIX free beer, hard to beat.
| nec4b wrote:
| You do realize there is a lot of C code out there which has
| nothing to do with UNIX. Although I do remember when you
| once claimed C requires UNIX like OS to run. :)
| Koshkin wrote:
| Well, UNIX is surely responsible for C becoming popular
| (if not its being a thing in the first place).
| nec4b wrote:
| I'm not arguing that it is not? It's funny though how
| many people saw value in C but not in Algol. Maybe C has
| something going for it?
| pjmlp wrote:
| Free beer alongside a free beer OS, instead of paying
| thousands of dollars for timesharing OSes like VMS.
| nec4b wrote:
| I know you keep repeating it. You are conveniently
| ignoring plenty of other commercial OSs and languages
| which were successful.
| pjmlp wrote:
| UNIX is to C like the Web is to JavaScript.
|
| JavaScript also runs outside of the browser nowadays, so
| what.
| nec4b wrote:
| I don't know what are you trying to say? How does this
| follow from the parent post?
| pjmlp wrote:
| It follows that the Web made JavaScript unavoidable, then
| nodejs made it available everywhere else.
|
| Likewise UNIX made C unavoidable in systems programming
| for timesharing servers, eventually like JavaScript
| outgrew the browser, certain people wanted to run C in
| their microcomputers.
| nec4b wrote:
| I don't disagree with you on C being popular because of
| UNIX. I do disagree if you believe this is the only
| reason why it still enjoys popularity. And you are
| selling the UNIX authors short if you think they chose C
| just for the fun of it.
| Koshkin wrote:
| Then it would become Algol, wouldn't it?
| pjmlp wrote:
| So many features still missing.
| belter wrote:
| sgt wrote:
| Based on another thread - I think the following topic should be
| an interesting one for HN to chew on: If someone wanted to write
| systems type of programming (whether it be embedded or Unix tools
| or even writing a library), should they go for C (C23) or Rust
| today?
| mhh__ wrote:
| D is a better modern C than Rust.
|
| Rust is very nice, but if you just want a safer C that will
| actually make you more productive versus less productive until
| you understand how rust wants you to program then D is a better
| fit.
| Koshkin wrote:
| Agree. "A better C" than C++ claims to be.
| adrianN wrote:
| I don't think that can be answered in general. It depends on
| what exactly you want to do and the maturity of the libraries
| in that area, and how security critical your application is.
| dureuill wrote:
| > the maturity of the libraries in that area,
|
| While true for C++ which is not very interoperable, C being
| very interoperable means that there is no advantage into
| using a C API from C rather than from Rust.
|
| > how security critical your application is.
|
| Rust also has productivity and general "correctness"
| advantages that go beyond security (although yes that alone
| is a factor)
| pkrumins wrote:
| Definitely C!
| bruce343434 wrote:
| I'm going for C, because I am experienced with C and despite it
| being more tedious, with having to do everything yourself, I
| stick with it because the compile times, and in fact the
| compile process, are so much faster and simpler. I really enjoy
| the direct feedback I can get. I considered C++ but that too
| had terrible compile times. Ideally a debug build should simply
| not take longer than 100ms for a codebase that isn't even
| 5KLoc, and only C seems to be able to offer that experience.
| gefhfffh wrote:
| I get that the compile process is faster, but simpler?
|
| In my experience, the compile process usually consists of
| "cargo build"
|
| A advantage of Rust is that usually you spend way less time
| debugging, because the compiler prevents many mistakes from
| compiling in the first place.
| bruce343434 wrote:
| I have an IDE with clang-lint and I find that it can spot
| pretty much every mistake. It can even detect some lifetime
| issues. Other than that my programming style is very much
| pass-by-value, trust the compiler to inline it, so the
| typical memory safety issues are simply not relevant to me.
| pornel wrote:
| Pass-by-value and let LLVM clean it up is also the
| idiomatic Rust way. rust-analyzer is pretty good for IDE
| integration, and it will catch way more than clang-lint
| (global lifetime analysis with guaranteed correctness,
| not just best-affort local, and thread safety/data
| races).
|
| Regarding compile times, Rust has a different approach.
| Instead of a fast cycle of run and see if it broke, it's
| more of following compiler nags until the program is
| correct and runs on the first try. Incremental (cached)
| compile times aren't too bad these days.
| gefhfffh wrote:
| Before I tried Rust (I got sick of it and the slow
| progress of Herb Sutter's research), I have used CLion
| with clang-tidy and had plenty of memory issues going
| undetected.
|
| Needless to say I didn't restrict myself to pass-by-value
| (compatible -> structs with ptrs are problematic as well)
| style, which seems quite restrictive
| pjmlp wrote:
| With current ISO C++ velocity and the stance to keep
| doing language evolution in person meetings, I don't
| think Herb's proposals will ever come to be, and even if
| they do, it won't matter when they most likely can only
| make it post-ISO C++26 with best efforts.
| flyinglizard wrote:
| Why does it matter if compile time is 100ms or 300ms? At even
| a second, that's going to be so negligible in the context of
| code-compile-debug work. Especially if something like a flash
| download is involved.
| bruce343434 wrote:
| 0. it is a noticeable delay and impinges my momentum
|
| 1. A flash download is not involved
|
| 2. I hardly debug. I seem to be in a minority here, but my
| linter really does catch pretty much everything. I don't
| blindly write code, I always ponder my approach first.
|
| So basically, the compile times pull me out of the flow.
| zh3 wrote:
| Very much with you on this one. Even with 50k+ LoC a
| 'make clean;make' takes less than a second (with help
| from ccache and a RAM disk). It effectively gets the
| compiler out of the way and keeps the thought processes
| continuous.
|
| One trick I like is to have a 2nd terminal watching the
| file(s) I'm editing, triggering a make/run on each save;
| building and running is then a single keypress away:-
| while [ 1 ]; do inotifywait -e move_self foo.c
| cc foo.c -o foo && ./foo # or 'make && ./foo' done
| flohofwoe wrote:
| The compilation time difference between C and Rust for
| nontrivial projects is much bigger than 3x.
| truffdog wrote:
| Are there features you can ban in your style guide to
| prevent serious compile time problems?
| OJFord wrote:
| Are your rust builds really that fast? Wth am I doing
| wrong! I'd love to measure it in seconds.
| jamincan wrote:
| It's slow for me, but I'm not working on a very powerful
| machine.
|
| That said, cargo check is fast, and my general experience
| with Rust is that it generally works once it compiles.
| People getting into more advanced features might have
| different experiences.
| CyberRabbi wrote:
| I'm going for C because programming language choice is a
| matter of personal preference in essence and Rust annoys me.
| sgt wrote:
| How does it annoy you? Development velocity, creativity
| hinderance?
| dureuill wrote:
| You could get productive in Rust in 3 months max, and then
| the productivity gains would quickly outweigh the initial
| investment
| donkarma wrote:
| Rust code takes longer to write than C code
| pornel wrote:
| It does for a novice. But once you learn Rust, it's
| actually quite productive. Rust has proper collections,
| strings, iterators, automatic (but not GC) memory
| management, error propagation, etc. This eliminates a lot
| of busywork, and makes Rust "denser", so you write less
| code, but get more done.
| hyperman1 wrote:
| No, the greenfield coding phase of Rust will always take
| longer than the same code in C: Rust will require you to
| think things through, while C by default accepts any
| morass of half-defined code.
|
| The eventual rust code+debug+maintain speed will be
| higher than the equivalent C speed, for the same reason.
|
| This means that rust is slower for vanity projects that
| won't be used in practice, or for low quality products
| with an attitude a la hack it- ship it - hide for
| customers - start next mess. The scary part: this is
| actually an existing corner of our market.
| dureuill wrote:
| My experience is mainly with C++, but from my own
| evaluation I'm x2 to x3 more productive overall in Rust
| than in C++. The reasons are a simpler build system that
| makes using the ecosystem faster, more expressive type
| system (iterators with combinators, sum types), the
| safety part that allows to not accidentally introduce UB
| and to not waste time with static and runtime analysis,
| shortening debug and review time. This compounds over
| time to give a better maintenance time.
|
| I don't have a similar evaluation for C <-> Rust, but I
| suspect the result would be even more skewed in Rust's
| favor: sure, you might be writing individual lines faster
| in C, but the lack of iterators, generics, traits and
| RAII, and the relative difficulty to use dependencies
| means that you will waste a lot of time reinventing the
| wheel, often suboptimally.
| drran wrote:
| Total time of <<coding + debugging>> (development time)
| is shorter for safe Rust, because Rust eliminates few
| classes of errors. Unsafe Rust and C are same, but Rust
| have better abstractions (match operator, Rust enum's,
| typed macros, etc.)
| pjmlp wrote:
| Neither, unless we are speaking of kernel and drivers kind of
| systems programming, in which case I would pick Rust.
|
| For anything else, a language with automatic memory management.
| Koshkin wrote:
| I wish D was more widely used, as it seems to be good as a
| systems language, too.
| pjmlp wrote:
| Me too, unfortunately the lack of focus has allowed the
| competition to step in, so at this point it is hard to tell
| what would be the killer application that can make it take
| off.
| dureuill wrote:
| In general, I think they should go for Rust. See [1].
|
| Now, embedded is a special case. You need platform support, and
| possibly certification, none of which are a given in Rust
| today. Arguably, not in C23 either at the moment, though.
|
| [1]: http://cliffle.com/blog/prefer-rust/
| [deleted]
| childintime wrote:
| > In its London 2019 meeting, WG14 has found consensus to elevate
| false and true to proper keywords.
|
| The committee settled this over a beer, or some other substance?
| Because the elevation to a proper type is opportunistic at best,
| and against the spirit of C at worst. Next people celebrate this
| with the use of capslock.
|
| The futility of it all blows my mind :C
| duskwuff wrote:
| The "bool" type, as well as defines for "true" and "false",
| already existed in <stdbool.h> [1]. What these proposals [2]
| intend to change is making them real keywords, rather than
| macros which expand to _Bool and appropriate integer values.
|
| [1]:
| https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/st...
|
| [2]: http://www.open-
| std.org/jtc1/sc22/wg21/docs/papers/2021/p231... and
| http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p231...
| jb1991 wrote:
| > the elevation to a proper type is opportunistic at best, and
| against the spirit of C at worst
|
| Can you explain what you mean by this?
| aliswe wrote:
| > This is only one meeting. We have like 5 more before C23, and
| only ~2 more before it's ISO Draft Ballot time
| blastonico wrote:
| > [dropped] Representations for signed integers other than two's
| complement
|
| May I assume that there won't be signed int undefined behavior
| after C23? INT_MAX + 1 == INT_MIN?
| Someone wrote:
| I doubt it, and wouldn't want it. It would break all kinds of
| optimizations. For example, with wrapping
| for(int i = 0; i <= m; i++) { foo(); }
|
| Wouldn't terminate if _m = INT_MAX_. That means compilers
| either have to special-case that value, or can't use the loop
| instructions of some CPUs (M68000 has "decrement and branch if
| larger than zero", for example)
|
| Also, with wrapping, _a[i]_ and _a[i+1]_ aren't guaranteed to
| be adjacent. That can make auto-vectorisation difficult.
| hfsrgbcfuknbft wrote:
| Those things are very subtle and complex, so I'm not 100%
| sure, but I think your first example is not great:
| For example, with wrapping for(int i =
| 0; i <= m; i++) { foo(); } Wouldn't
| terminate if m = INT_MAX.
|
| This is undefined behavior in the current standard when m =
| INT_MAX. The condition i <= m is always true and i will
| overflow. So it could result in an infinite loop (or worse).
| AFAICT, with wrapping signed ints, it would infinite loop but
| at least not yield UB?
| Someone wrote:
| Yes, for _m = INT_MAX_ and wrapping signed int, it is
| undefined behavior.
|
| Because of that, the compiler is allowed to assume _m [?]
| INT_MAX_ , and that can mean it can generate more efficient
| and/or smaller code.
|
| Assuming _m [?] INT_MAX_ isn't (considered to be [1]) a big
| loss because chances are the programmer who wrote that
| didn't intend to write an infinite loop.
|
| [1] of course, is an opinion, but it's the opinion the
| standards writers have had for decades.
| pwdisswordfish9 wrote:
| > Oh, and a big deal: true/false are KEYWORDS NOW, and all of the
| bool/thread_local/etc. are all KEYWORDS NOW!!!!
|
| Why does it even matter? I could take true and false to be an
| improvement (having them as macros expanding to int literals had
| its problems, but even for that one I would not mind _True and
| _False at all), but the rest? Who cares? It's literally the least
| significant change.
___________________________________________________________________
(page generated 2022-02-19 23:01 UTC)