[HN Gopher] Checked C
___________________________________________________________________
Checked C
Author : soheilpro
Score : 134 points
Date : 2022-12-21 18:29 UTC (4 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| kelnos wrote:
| Thinking about this at a higher level, the real problem is that
| we use C arrays at all. But we can't stop using C arrays, because
| libc and a huge body of other C libraries out there represent
| lists of data using C arrays.
|
| As a useful counterexample, glib has GArray, GPtrArray, and
| GList, along with functions that you use to manipulate the lists.
| Those functions are presumably implemented correctly, and will
| prevent you from making out-of-bounds accesses.
|
| But of course those things are not widely adopted, because
| they're not standardized, they're not in libc, and libc has not
| been reimagined such that all of its APIs take and return these
| safer list primitives instead of bare C arrays.
|
| (And sure, GArray etc. are not necessarily suitable everywhere,
| as they require heap allocations. But I could imagine a safe
| abstraction that could allow for using stack or static
| allocations to back it.)
|
| So I see something like Checked C as a band-aid, when the
| language and stdlib just needs a complete overhaul. Obviously
| that's incredibly unlikely to ever happen, so something like
| Checked C is a decent compromise, I guess.
| sramsay wrote:
| > As a useful counterexample, glib has GArray, GPtrArray, and
| GList, along with functions that you use to manipulate the
| lists. Those functions are presumably implemented correctly,
| and will prevent you from making out-of-bounds accesses.
|
| > But of course those things are not widely adopted, because
| they're not standardized, they're not in libc, and libc has not
| been reimagined such that all of its APIs take and return these
| safer list primitives instead of bare C arrays.
|
| I'm really not sure why the second thing is regarded by C
| programmers as such an insuperable barrier to the first thing.
|
| I absolutely understand that there are circumstances where
| extreme portability is a major requirement. That, and C's
| ability to operate in highly constrained environments are among
| its most laudable features.
|
| But many of us (including me) write user-facing C applications
| that have neither requirement and where Glib is either already
| installed or easy to install. Why not just go ahead and use it?
| If you're trying to get it to run on a tiny embedded system or
| in some land without Glib . . . well, this isn't the program
| for you!
|
| I feel like this is more of a weird cultural prejudice than a
| technical matter. People run programs in JavaScript (or
| Haskell, or Python) with _hundreds_ of dependencies, and while
| some find that annoying, I don 't hear people in these
| communities objecting to _idea_ of dependencies the way people
| do with C.
|
| Could the standard library be better? Of course. But there's
| something to be said for not including a lot of batteries in
| the _standard_ and just using the third-party tools that are
| available.
| emmanueloga_ wrote:
| Does anybody know how does this compare to https://compcert.org/
| ?
| ryao wrote:
| It does not. One is a language extension that claims to prevent
| certain classes of issues. The other is a C compiler that
| claims to do nothing to prevent those classes of issues. The
| two are not comparable at all.
|
| You would be better off comparing it to Astree, which is a
| static analyzer written by the group that wrote the Compcert C
| compiler.
|
| https://www.absint.com/astree/index.htm
|
| Astree claims to be able to prove the absence of use-after-
| free, which the checked C documentation says that checked C
| does not prevent.
|
| You would need to check to see if Astree can prove the absence
| of all of the issues that checked C is intended to prevent, but
| at a glance that seems possible. In theory, Astree can be used
| to fix all of them by doing fixes until it stops complaining.
| belter wrote:
| "A Formal Model of Checked C" -
| https://news.ycombinator.com/item?id=30321535 - 37 comments - 10
| months ago
|
| "Checked C" - https://news.ycombinator.com/item?id=26190403 - 133
| comments - 2021
|
| "Refactoring the FreeBSD Kernel with Checked C" -
| https://news.ycombinator.com/item?id=25989115 - 41 comments -
| 2021
|
| "Achieving Safety Incrementally with Checked C" -
| https://news.ycombinator.com/item?id=19424106 - 21 comments -
| 2019
|
| "Checked C: Making C Safer by Extension" -
| https://news.ycombinator.com/item?id=17939537 - 55 comments -
| 2018
|
| "Checked C: extension to C that adds static and dynamic checking"
| - https://news.ycombinator.com/item?id=16588483 - 92 comments -
| 2018
|
| "Checked C" - https://news.ycombinator.com/item?id=11899925 - 156
| comments - 2016
| dang wrote:
| Thanks! Added a few:
|
| _C to Checked C by 3C_ -
| https://news.ycombinator.com/item?id=30857289 - March 2022 (1
| comment)
|
| _A Formal Model of Checked C_ -
| https://news.ycombinator.com/item?id=30321535 - Feb 2022 (37
| comments)
|
| _Why Checked C when there was Verona?_ -
| https://news.ycombinator.com/item?id=26499846 - March 2021 (2
| comments)
|
| _Checked C_ - https://news.ycombinator.com/item?id=26190403 -
| Feb 2021 (133 comments)
|
| _Refactoring the FreeBSD Kernel with Checked C [pdf]_ -
| https://news.ycombinator.com/item?id=25989115 - Feb 2021 (41
| comments)
|
| _Refactoring the FreeBSD Kernel with Checked C [pdf]_ -
| https://news.ycombinator.com/item?id=24019185 - Aug 2020 (13
| comments)
|
| _Achieving Safety Incrementally with Checked C_ -
| https://news.ycombinator.com/item?id=19424106 - March 2019 (21
| comments)
|
| _Checked C: Making C Safer by Extension_ -
| https://news.ycombinator.com/item?id=17939537 - Sept 2018 (55
| comments)
|
| _Checked C: extension to C that adds static and dynamic
| checking_ - https://news.ycombinator.com/item?id=16588483 -
| March 2018 (92 comments)
|
| _Checked C_ - https://news.ycombinator.com/item?id=12049548 -
| July 2016 (3 comments)
|
| _Checked C - A Safer C /C++ from Microsoft_ -
| https://news.ycombinator.com/item?id=11936418 - June 2016 (3
| comments)
|
| _Checked C_ - https://news.ycombinator.com/item?id=11899925 -
| June 2016 (156 comments)
| WalterBright wrote:
| Checked C: int a[5] = { 0, 1, 2, 3, 4};
| _Array_ptr<int> p : count(5) = a; // p points to 5 elements.
|
| My proposal for C: int a[5] = { 0, 1, 2, 3, 4};
| int p[..] = a; // p points to 5 elements.
|
| https://www.digitalmars.com/articles/C-biggest-mistake.html
|
| https://github.com/Microsoft/checkedc/wiki/New-pointer-and-a...
| elcritch wrote:
| I like your version, but how do you annotate the size from
| existing things like "main(int *argv, argc)" to know that the
| size is argc?
| wahern wrote:
| There was a proposal during the C23 process to make "main(int
| argc, char *argv[argc])" work as one would expect, as well as
| some similar changes elsewhere, such as with structure
| members. They went through several revisions but never made
| the cut, I think partially because they all required at least
| some minimal backward incompatibility.
|
| IMO, if GCC or clang implemented and ran with those proposed
| changes, they'd probably be accepted for the next C revision,
| and become popular long before then. This is mostly a matter
| of time and motivation; corporate funded developer time seems
| to be mostly focused on half measures; e.g. type attributes,
| rather than fundamentally improving pointer and array
| semantics. But if someone put in enough time and effort,
| including going through the rigmarole of integration into
| mainline, this could happen.
| kelnos wrote:
| You just... annotate it? Like, I don't see what the issue is.
| You just write int main(int argc, char
| **argv : count(argc)) {}
|
| If you're already creating an extension for C, then it's fine
| to "change" its signature in this way. Or am I
| misunderstanding your objection?
|
| Sure, the compiler can't verify that argv does indeed have
| argc elements, but hopefully we can rely on the kernel and C
| runtime to populate things properly. If not, I would say it
| doesn't matter that the compiler can't help you here; your
| system is screwed beyond repair already.
|
| At the very least, the compiler _can_ emit bounds checking to
| ensure that you don 't try to access past argc elements in
| that array, which is still valuable.
|
| Edit: it occurs to me that you were talking about
| WalterBright's version, not the version in Checked C. But I
| think my comment still applies: if you're changing how things
| work, then you just keep changing how things work to cover
| cases like this.
| WalterBright wrote:
| Create an adapter: int main(int argc, char
| **argv) { return myMain(argv[0 .. argc]); }
|
| Strings can be done like this: char [..] s
| = p[0 .. strlen(p)];
| elcritch wrote:
| Hmmm, the "[..]" is a fat pointer right? Couldn't you just
| say: int main(char [..] args)
|
| Maybe with some way to tell the compiler the correct
| parameter order if needed? Perhaps: int
| main(char [..argc] argv)
|
| I'm curious if ELF and other formats have enough info to
| figure that mapping out?
| WalterBright wrote:
| > the "[..]" is a fat pointer right?
|
| yes
|
| > if ELF and other formats have enough info to figure
| that mapping out?
|
| No, as there is no semantic connection between `argc` and
| `argv`.
| tomcam wrote:
| Elegant, but of course it would be. It's like you're a trained
| professional or something ;)
| WalterBright wrote:
| not my first rodeo! ABEL was the first language I designed
| (for Data I/O) back in the 80s.
|
| ABEL = "Advanced Boolean Expression Language", a language for
| programming PLDs (Programmable Logic Devices) which was a
| core business for Data I/O.
| bachmeier wrote:
| There's no substitute for decades of having programmers
| giving you (and shouting at you) blunt feedback on your
| programming language proposals.
| WalterBright wrote:
| Here's the timeline:
|
| 1. who would do such a dumb feature
|
| 2. what, are you insane?
|
| 3. it becomes obvious
|
| 4. other languages adopt it
| gavinray wrote:
| You might show an example of how to use D's templates (if it's
| possible) to emulate the more complex example of computing the
| bounds from an input argument char
| *strncpy(char * restrict dest : count(n),
| const char * restrict src : count(n), size_t
| n) : bounds(dest, (_Array_ptr<char>)dest + n);
| WalterBright wrote:
| https://news.ycombinator.com/item?id=34085835
| gavinray wrote:
| I meant something more like this (although this doesn't
| QUITE compile, but it's close I think):
| static ubyte* [n*2] requires_ptr_twice_as_large_as_input(n
| : uint) ( ubyte*[n] input,
| ubyte*[n*2] output, ) { output[0..n] =
| input[0..n]; output[n..2*n] = input[0..n];
| return output; } void main() {
| ubyte[10] input = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
| ubyte[20] output = new ubyte[20];
| requires_ptr_twice_as_large_as_input!(10)(&input, &output);
| }
| KingLancelot wrote:
| Fat pointers are a good idea, but I think it'd be a better idea
| to store the start and evd pointers instead of a pointer to the
| first element and a size_t.
| 1980phipsi wrote:
| Why?
| masklinn wrote:
| I'd guess it's because that's what C++ does. Though it's
| unclear to me that C++-style iteration (where you increment
| a running pointer until you reach an EOI pointer) is much
| used in C.
| WalterBright wrote:
| Storing two pointers into the same array is a memory
| safety problem. It's hard to implement a borrow checker
| when there are two live mutable pointers into the same
| memory object.
| sirwhinesalot wrote:
| It's a shame this will never get through the insane bureaucracy
| that is the C standards committee. Had they listened to you all
| the way back in 2009, C11 might have been a game changer the
| same way C++11 was. Alas.
|
| At least there's BetterC ;)
| WalterBright wrote:
| This proposal could very well save C, as array bounds
| overflows are consistently the #1 cause of corruption bugs in
| shipped C software.
| ryao wrote:
| In theory, sound static analyzers could be another method
| by which this is achieved in existing projects. They claim
| to be able to catch all instances of this. Some examples of
| sound static analyzers include:
|
| https://www.absint.com/astree/index.htm
|
| https://github.com/NASA-SW-VnV/ikos
|
| https://github.com/static-analysis-engineering/CodeHawk-C
|
| I have planned to try using them on OpenZFS for a while,
| but I am still busy reviewing and fixing reports made by
| conventional static analyzers. I plan to look into these
| next.
|
| That said, at least one of them claims to be able to prove
| the absence of issues in C that checked C's documentation
| explicitly says it cannot prevent. The obvious one is use-
| after-free.
| WalterBright wrote:
| I don't know how a static analyzer could do this:
| size_t i = some_function(); // gets return value from
| environment array[i] = 3;
| roywiggins wrote:
| If it's sound it will point out that there's a potential
| for an error if it can't prove otherwise. To silence the
| error you'd have to manually put a check in.
| ryao wrote:
| A sound static analyzer in theory can check the safety of
| that by examining all code paths and complain whenever
| any exist where it is possible to go out of bounds. It is
| called sound because the absence of a complaint means it
| has proven the absence of the issues it is meant to
| catch.
| jeffybefffy519 wrote:
| It doesnt need to get through any committees to have impact.
| Microsoft just has to use it (which i assume they are given
| they are the authors) and then its had impact.
| adastra22 wrote:
| I don't think the comment you are replying to is talking
| about MSFT's Checked C?
| ryao wrote:
| Do they still refuse to update their compiler to support
| any version of C beyond C89?
|
| Unless they have changed course, it seems more likely that
| Microsoft will drop NT for a UNIX kernel than Microsoft
| would put this into their compiler. I assume that this is
| by Microsoft Research and work by Microsoft Research is
| almost never used by Microsoft. The only exception I know
| is Drawbridge, which they reportedly used in Azure.
| my123 wrote:
| SQL Server on Linux runs on Drawbridge, with NTUM and
| all.
| ryao wrote:
| > It's a shame this will never get through the insane
| bureaucracy that is the C standards committee. Had they
| listened to you all the way back in 2009, C11 might have been
| a game changer the same way C++11 was. Alas.
|
| This comment did not age well:
|
| https://news.ycombinator.com/item?id=34086304
|
| A quick test with `clang -std=c89 -pedantic` says it was in
| C99. Amazingly, it seems that almost nobody knew about it.
| sirwhinesalot wrote:
| Not the same thing at all, that only works with compile-
| time known sizes.
| WalterBright wrote:
| Pascal arrays were fixed at compile time, which I quickly
| discovered made Pascal rather useless without extensions.
| ryao wrote:
| The example was for compile-time known sizes.
| Xeoncross wrote:
| Yes, needing a fixed-sized array seems like a fairly common
| need to me. a := [5]int32{0, 1, 2, 3, 4} //
| Go let mut array: [i32; 5] = [0, 1, 2, 3, 4]; //
| Rust
| masklinn wrote:
| C has fixed-size arrays.
|
| The problem is that it doesn't use them much, and gets rid of
| them as soon as possible: int a[5] = {1, 2,
| 3, 4, 5, 6}; printf("%d\n", a[8]);
|
| in clang, this warns, by default, on both misuse sites
| "excess elements in array initializer" and "array index is
| past the end of the array". Which is good.
|
| However things go downhill as soon as you pass the arrays
| downstack: #include <stdio.h>
| static void foo(int *a) { printf("%d\n", a[8]);
| } static void bar(int a[]){
| printf("%d\n", a[8]); } static void qux(int
| a[6]){ printf("%d\n", a[8]); }
| int main() { int a[5] = {1, 2, 3, 4, 5};
| foo(a); bar(a); qux(a); }
|
| no warning anywhere, even under "-Wall -Weverything".
| [deleted]
| klodolph wrote:
| Yeah, so the syntax is a bit funny but you can actually get
| the bounds checking you want here: #include
| <stdio.h> static void qux(int a[static 6]){
| printf("%d\n", a[8]); } int main() {
| int a[5] = {1, 2, 3, 4, 5}; qux(a); }
|
| I get, test.c:9:5: warning: array argument
| is too small; contains 5 elements, callee requires at least
| 6 [-Warray-bounds]
|
| I did not enable any warning flags at all, this is just
| default Clang on a Mac.
|
| If you want to catch the a[8] inside the function you need
| something else.
| ryao wrote:
| It appears that Clang will warn even without this syntax
| while GCC does not warn unless it has this syntax. At
| least, it did when I dropped the `static 6` from the
| example.
| Jasper_ wrote:
| Unfortunately, `int a[static 3][static 4]` does not work.
| klodolph wrote:
| That's because you'd write it as: int
| a[static 3][4]
|
| You only need to put static on the outermost type, the
| one that decays into a pointer. Same thing applies if you
| need restrict: int a[static restrict
| 3][4]
|
| which is ugly but gets the job done. Think of int
| a[3][4], when used as a function parameter, as "pointer
| to int[4]" (the 3 disappears completely), and think of
| int a[static 3][4] as "pointer to first of at least 3
| int[4]".
|
| (Not trying to defend C here, just explaining how C
| works.)
| WalterBright wrote:
| The explicit "6" is a problem if you aren't using fixed
| size arrays.
| klodolph wrote:
| Yes, this was in direct response to someone talking about
| fixed-size arrays. Think of this as just "one small way
| in which C does not happen to be broken" rather than some
| kind of endorsement of C!
|
| Note that you could static void qux(int
| n, int a[n])
|
| but this changes the interface somewhat and there are
| lots of reasons why you might want to avoid VLAs in C.
| WalterBright wrote:
| The problem with that syntax is you have to repeat it
| every time `a` is forwarded to another function. The
| array data and length need to be combined into a single
| semantic entity.
| klodolph wrote:
| Yes, but I don't think a deeper discussion about the
| flaws of array handling C is really going to illuminate
| anything here. The conclusions generally go in one of
| three ways--either you choose to use a different
| language, choose to deal with C (with tools like static
| analyzers or instrumentation), or choose to make
| proposals to the C committee.
|
| Proper array types are not present in C and they're
| unlikely to be added at any point in the future, so if
| the conversation is "the array data and length need to be
| combined into a single semantic entity", then the
| conversation is no longer about C, but the starting point
| for choosing another language.
|
| The int a[static 6] syntax made it into the language
| because it's a small enough change that it's not
| disruptive to existing uses of C, but it still has some
| benefit (I've used it, I've seen its benefits).
| WalterBright wrote:
| My proposal is backwards compatible and will not disrupt
| existing use.
| klodolph wrote:
| Do you have a write-up somewhere?
| gavinray wrote:
| Note that active development seems to be continuing here:
|
| https://github.com/secure-sw-dev/checkedc-llvm-project
| jimbob45 wrote:
| Why not just use C++?
|
| Also why can we not get better syntax for C? Function pointer
| syntax is so bad that people actively avoid using them. #pragma
| once is a hack. Every string library function is actively
| dangerous in addition to puts/gets.
|
| I know that nobody wants to be the one to mess with the core
| language and ruin it but this is awfully low-hanging fruit that
| hasn't been fixed in 50 years.
| flohofwoe wrote:
| The stdlib needs a modernization much more than the language,
| unlike 'C the language', 'C the stdlib' is still stuck deep in
| the K&R era (together with POSIX).
|
| For a different language syntax it makes a lot more sense to
| consider using a different language in the first place though,
| because everybody has a different opinion what such a 'better
| C' syntax should look like (e.g. it sounds like you'd actually
| want Zig).
| omeysalvi wrote:
| >Why not just use C++?
|
| Nothing good has come to anyone who started an argument with
| those words.
| gavinray wrote:
| Am sort of curious what the difference is between this and
| templated constexpr functions with span<T, N> in C++
| mirekrusin wrote:
| It has been fixed. The fix has the codename "zig".
| pjmlp wrote:
| It isn't a fix when it still allows for use after free.
| shrimp_emoji wrote:
| I heard it was "Rust".
| anfilt wrote:
| Rust is not exactly a C replacement. Definitely the better
| choice these days over C++ in my opinion if you can use
| rust.
|
| It can be made to function more like C with #![no_std].
| However that is an even less than batteries included
| experience than C.
| masklinn wrote:
| > Rust is not exactly a C replacement.
|
| Rust is absolutely a C replacement.
|
| Whether C heads want to use it is a more complicated
| question. But some are very much into it (e.g. Brian
| Cantrill).
|
| > It can be made to function more like C with #![no_std].
| However that is an even less than batteries included
| experience than C.
|
| std assumes you have a heap and IO, which most C
| environments do.
|
| no_std removes all that (leaving only libcore as
| baseline), however you can re-add a dependency on "alloc"
| to get allocations and most of the standard collections
| back (all but hashset and hashmap, because no secure
| RNG).
|
| You can also / instead fill your needs with third-party
| crates more dedicated to restricted or freestanding
| environments, like heapless
| (https://crates.io/crates/heapless).
| tialaramex wrote:
| You get a lot more in core (and thus no-std) than the
| free standing C language.
|
| For example C's qsort lives in the standard library,
| whereas in Rust although [].sort() needs alloc, the
| [].sort_unstable() is a core feature!
|
| str::split_once(['5', '7']) will split a string at the
| first digit 5 or 7... You need considerable work to do
| that in C, and doing it modifies the string. In Rust it's
| a core feature.
|
| Of course Rust is relying on the fact that none of the
| machine code is emitted unless you use these features,
| indeed split_once is fully generic, the types used only
| come into existence because you called the function. So
| presumably this was not practical as the fundamental
| language for writing Unix fifty years ago.
| maxbond wrote:
| I think you & GP are using different senses of
| replacement ("drop in replacement" vs. "replacement for
| greenfield projects"). You might consider Rust to be the
| latter (with qualifications, eg, excluding certain
| architectures & proprietary programming environments) but
| it's explicitly not the former (it's interoperable with
| C, but not compatible with C).
|
| I think we should avoid saying "replacement" in general
| because eliminating all lines of C isn't a goal worth
| pursuing, C doesn't need to die for Rust to succeed, and
| there's room enough in this world for a hundred safe
| systems languages fulfilling different niches. I think a
| lot of people feel attacked & invalidated by the idea of
| a "C replacement" that isn't C compatible, like we're
| telling them their skills are no longer necessary or
| valuable, which is untrue & leads to flamewars and
| misunderstandings.
| zozbot234 wrote:
| Rust is absolutely a "drop-in" replacement to C in most
| cases even for existing projects, it was absolutely built
| with that goal in mind. You can go as fine-grained as
| replacing a single function with a Rust-coded version
| (even using bindgen to ingest existing C headers) -
| though that generally involves unsafety because you're
| dealing with general pointers, extern calls and such.
| Even Checked C cannot prove these things 100% safe, it
| just catches common misuse.
|
| (Of course some C projects could abuse the preprocessor
| in ways that make it infeasible to even replace a C
| function with a Rust equivalent, but that's incredibly
| rare. And Rust has macro facilities of its own.)
| chaosite wrote:
| Rust is more comparable to C++ than C.
| seanw444 wrote:
| Looking forward to it becoming more mature. Really cool
| language.
| constantcrying wrote:
| >Also why can we not get better syntax for C?
|
| Backwards compatability.
|
| >Function pointer syntax is so bad that people actively avoid
| using them.
|
| That is because C syntax mistakenly put the return value before
| the parameters. You use function pointers if you have to.
|
| >#pragma once is a hack.
|
| It is a hack to prevent the previous hack of #ifdef'ing the
| thing.
|
| >but this is awfully low-hanging fruit that hasn't been fixed
| in 50 years.
|
| It is literally impossible to fix.
| jimbob45 wrote:
| There are ways to fix backwards compatibility, no? You
| introduce the new syntax, let it sit for several years, and
| then deprecate the old syntax. Would it truly be that
| difficult to introduce a "fn" keyword? Also #includeHeader
| "myHeader.h" would solve the #pragma once problem.
|
| I simply can't tell if we're not fixing this stuff out of
| laziness, out of fear, or because no one wants to admit that
| no one knows who's holding us back.
| constantcrying wrote:
| C++ addresses most of your concerns already. The headers
| are C++23 iirc, somewhat similar to your proposal.
|
| I don't think you really understand what C actually is. C
| basically does not compete as a programming language. On a
| UNIX like it is the language of the kernel and as such its
| quirks inevitably represent the quirks of the kernel, you
| use C if you want to talk to the kernel.
|
| >Would it truly be that difficult to introduce a "fn"
| keyword?
|
| Yes, literally impossible. Just look at the controversy of
| C23 removing the almost entirely unused K&R function
| declaration syntax.
| elcritch wrote:
| Ugh, the C syntax makes it so hard to parse, humans or
| machine.
|
| I recently submitted a PR for the `c2nim` import tool to
| handle double function pointers. I didn't actually understand
| the C code until I got the transpiler working despite
| cdecl.org: // posix signal
| void(*signal(int, void (*)(int)))(int);
|
| in Nim becomes: var signal*: proc (a1:
| cint; a2: proc (a1: cint)): proc (a1: cint)
|
| Well I'm 99.5% certain at least. Even now I'm uncertain of
| the C syntax. And I've not been bold enough to test 3rd order
| C function pointers. I figure that's probably C code you
| don't wanna touch if possible.
|
| https://github.com/nim-
| lang/c2nim/blob/11f2c5363dfe7e8c7c8ce...
|
| The other annoying one is that "signed" and "unsigned" are
| basically adjectives, but "long" can be both a type and a
| modifier. So it's difficult to parse unless you're the target
| C compiler. Technically you can, but you have to use
| backtracking.
| secondcoming wrote:
| That nim version isn't much better IMO, but I am unfamiliar
| with the language.
| kelnos wrote:
| I'm completely unfamiliar with the language but was able
| to read it from left-to-right very easily:
| var signal*: proc (a1: cint; a2: proc (a1: cint)): proc
| (a1: cint)
|
| That reads to me as:
|
| Variable signal is a pointer to a function that that
| takes two arguments (an int, and a function that takes an
| int), and returns a function that takes one argument (an
| int).
|
| Of course, I'm assuming my interpretation is correct...
| perhaps it's not ;)
| elcritch wrote:
| That's right. It's actually just an ugly bit of code
| though it's pragmatic.
|
| Note that Nim uses "*" as a public symbol sigil not a
| pointer. Its a bit odd at first coming from C but is nice
| and consistent.
| shirleyquirk wrote:
| I agree, I prefer Nim's alternate syntax for this sort of
| stuff: var signal*: (cint,(cint)->void)
| -> (cint)->void
| slavik81 wrote:
| The signed and unsigned keywords work the same way as long,
| e.g., `unsigned` alone is equivalent to `unsigned int`.
| elcritch wrote:
| Yah but you can't have "unsigned unsigned". You can and
| do have "long long", or possibly a "long long long" in
| addition to the saner "long int".
| constantcrying wrote:
| >Yah but you can't have "unsigned unsigned".
|
| Seems like a good thing to be honest.
| elcritch wrote:
| Lets not give the C committee ideas ;)
|
| But actually I'd suggest the opposite of disallowing
| "long long" and making it like signed/unsiged as purely a
| modifier.
| xormapmap wrote:
| > void( _signal(int, void (_ )(int)))(int);
|
| This is trivial to parse if you use spiral rule, humans or
| machine.
| constantcrying wrote:
| >Ugh, the C syntax makes it so hard to parse, humans or
| machine.
|
| As a _generalization_ I completely disagree. But for
| function pointers specifically, yes, they are easily the
| worst part of the C syntax.
|
| >void( _signal(int, void (_ )(int)))(int);
|
| That's just declaring signal as function (int, pointer to
| function (int) returning void) returning pointer to
| function (int) returning void, DUH. Thank you cdecl.org
|
| But notice how absolutely ugly it is that the final return
| type comes _first_ , that is due to the C function
| signatures.
| WalterBright wrote:
| > difficult to parse
|
| Not really. Just create a bit mask.
|
| https://github.com/dlang/dmd/blob/master/compiler/src/dmd/c
| p...
| elcritch wrote:
| Thanks! I'd read you had a full c compiler, this is
| awesome.
|
| Looks like there's only about ~388 lines of logic to the
| bitmask? haha your definition of difficult might not
| match mine. ;)
| [deleted]
| WalterBright wrote:
| D has had a BetterC subset of D for a while:
|
| https://dlang.org/spec/betterc.html
| nottorp wrote:
| Hmm. Didn't Turbo Pascal have array bounds checking 3 billion
| years ago when we all had pet dinosaurs? It could have simply
| been added to the compiler in C as well...
| baq wrote:
| Turbo Pascal had a lot of good ideas back in the late 80s and
| early 90s which were ridiculed back then and are now considered
| best practices... modules, safe strings, safe arrays, Delphi
| added quite nice objects. Alas, it was never popular in the
| Internet age. Just imagine if we had pascalscript instead of
| JavaScript - a decade of wasted developer time saved...
| timmg wrote:
| Quite honestly, I love what MS has done with JavsScript with
| Typescript. It would be great if they could do the same for C.
|
| I guess the hard part will be the fact that all your dependent
| libraries will (likely) still be unsafe.
| pjmlp wrote:
| See also https://devblogs.microsoft.com/cppblog/high-
| confidence-lifet...
| flohofwoe wrote:
| I'm a bit confused, at the start they talk about C++, but
| some of the code examples look like C. Do those checks also
| work in the C compiler? (the difference is kinda important,
| because unlike Clang, the MSVC C++ compiler doesn't have
| enough non-standard language extensions to compile C code
| that was written in the last 20 years).
| pjmlp wrote:
| They talk about C++, because that is what mostly matters to
| Visual C++ customers, however /analyse mode also works in C
| code.
|
| https://learn.microsoft.com/en-us/cpp/code-quality/code-
| anal...
| sendfoods wrote:
| I'm a bit confused. Didn't Herb Sutter essentially fork
| clang and extended the codebase in the beginning? Is
| microsoft working with that fork and (most importantly)
| re-contributing?
| phailhaus wrote:
| I'm begging them to do the same for Python.
| corndoge wrote:
| They made pyright which is pretty rad
| phailhaus wrote:
| Yeah it's pretty great, but still hamstrung by the inherent
| limitations of the language itself. Would love to see a new
| language on top of Python that treats types as first-class
| constructs.
| pjmlp wrote:
| Older discussions on Checked C,
|
| https://news.ycombinator.com/item?id=30321535
|
| https://news.ycombinator.com/item?id=19424106
| guerrilla wrote:
| Why not frama-c instead?
___________________________________________________________________
(page generated 2022-12-21 23:00 UTC)