Live data from Hacker News

Let's Destroy C

gist.github.com

161–170 of 192 posts

Re: Let's Destroy C

#161

Earlier quoted context omitted.

puts and printf aren't keywords, they're regular functions.

Well, sort of. Specifically, printf is an oddball function because it uses the varargs mechanism, and the whole format strings mechanism is inherently risky because it effectively bypasses the type system and says "trust me." Back when I was learning C, on a Mac with THINK C, misusing printf was a sure-fire way to crash the computer very quickly, especially since misaligned accesses of 16-bit or 32-bit words caused c…

Format strings (... at least, static format strings) don't have to bypass the type system.

Re: Let's Destroy C

#162

I've been a C programmer for several years now (out of necessity - C is still the best language for firmware and embedded development) There's been a lot of noise on the internet about Rust and C++20 and "modern" languages. I recently had an opportunity to try some of these first hand. Honestly the new language features are all terrible with few exceptions. In general, anything that was added to a language to support…

I understand it's against the rules to suggest someone hasn't read the article. But I think it's pretty clear from this comment that the article has zero to do with the posted article. The article's title was provocative and humorous, bc it's abt using C in a very peculiar way. It's not about the tired argument of "should we replace C with Rust/etc." which the above poster and many others have glommed onto. This wate…

[deleted]

Re: Let's Destroy C

#163
post #142
post #139

Earlier quoted context omitted.

> you can't remove undefined behaviors while at the same time keeping C like speed. This is absolutely correct. The specs of C allow so much undefined behavior in order to let the compiler just emit the instructions for the arithmetic operation or memory access or whatever. For edge cases like overflow and bounds, C deliberately says "not my problem" and you just get whatever that hardware architecture happens to do…

It's more that things were left undefined for portability and compiler authors (ab)used them for optimization enough for that to become de facto true (especially now that portability is easier).

And if all C users decided that, now that portability is much easier, it was time to define some of that behavior, it would happen.

But, as much as people want to blame optimizing compilers for their behavior around UB, absolutely no one is going to sacrifice C's performance for safety.

Re: Let's Destroy C

#164

I've been a C programmer for several years now (out of necessity - C is still the best language for firmware and embedded development) There's been a lot of noise on the internet about Rust and C++20 and "modern" languages. I recently had an opportunity to try some of these first hand. Honestly the new language features are all terrible with few exceptions. In general, anything that was added to a language to support…

Have you looked into Zig ( https://ziglang.org/ )? It's a little more than what you've asked since it does support compile time generics. But is specifically targeted at removing undefined behavior and improving safety.

I can second this recommendation. Zig is really the best language I seen so far at attempting to be a direct replacement to C (Rust is good too, but maybe a bit too advanced.. feels more like a C++ replacement)

The compile time generics is kind of necessary to replace some of the stuff people use C preprocessor macros for. I think Zig is just taking the idea of having compile time evaluation of code to its natural conclusion, and it ends up being a lot cleaner than C with preprocessor magic.

The only thing they've added which isn't necessary for a "better C", is the async stuff they're working on now. But I think it's still a good idea.

Re: Let's Destroy C

#165

I've been a C programmer for several years now (out of necessity - C is still the best language for firmware and embedded development) There's been a lot of noise on the internet about Rust and C++20 and "modern" languages. I recently had an opportunity to try some of these first hand. Honestly the new language features are all terrible with few exceptions. In general, anything that was added to a language to support…

> remove some of the undefined behaviors, There was a great talk from a C/C++ compiler writer about why you can't remove undefined behaviors while at the same time keeping C like speed. Simple example: accessing an array past it's end it's undefined behaviour. If you want to remove this, you need to add bounds checking (either to raise an error or to just return 0).

> There was a great talk from a C/C++ compiler writer about why you can't remove undefined behaviors while at the same time keeping C like speed.

I don't think this is true. Look at Zig, they don't seem to have a problem removing a lot of C's undefined behaviour, while still being able to surpass C in speed in many cases.

> Simple example: accessing an array past it's end it's undefined behaviour. If you want to remove this, you need to add bounds checking

Zig does indeed do bounds checking. I think the way it can still compete with C is: - Zig should be better at propagating constants (Better module system, Link-Time Optimization by default, and I think avoiding undefined behaviour helps here too). Arrays/slices do often have constant bounds. - You can choose to build with or without bounds checks (--release-safe, --release-fast). This means you're more likely to discover out of bounds problems during debugging, since you'll always get errors in those cases. But you have the option to release a fast version.

Julia has another interesting solution to bounds checking, where you can mark a piece of code with @inbounds to declare that you assume array access is within bounds.

I think some undefined behaviour can also be detrimental to performance. If you pass two pointers to a function, and it's undefined whether they alias or not, there are optimisations you can't do.

Re: Let's Destroy C

#166
post #112
post #38

Earlier quoted context omitted.

Most cases I've seen accept anything as true as long as the LSB is 1, and quite strictly 0 as false. Everything else is up in the air. The value -1 is definitely true. :)

> The value -1 is definitely true Except when being used as a comparison to any of the std utilities.

As far as I know, std library specifically uses the word "nonzero" in the documentation to denote non-false value. Therefore you should be using !, &&, || for any boolean ops, but never == nor !=

Re: Let's Destroy C

#167

Reminds me of Arthur Whitney's k.h[1] Example: // remove more clutter #define O printf #define R return #define Z static #define P(x,y) {if(x)R(y);} #define U(x) P(!(x),0) #define SW switch #define CS(n,x) case n:x;break; #define CD default 1 - https://github.com/KxSystems/kdb/blob/master/c/c/k.h

Or the J incunabulum[1] ...

  typedef char C;typedef long I;
  typedef struct a{I t,r,d[3],p[2];}*A;
  #define P printf
  #define R return
  #define V1(f) A f(w)A w;
  #define V2(f) A f(a,w)A a,w;
  #define DO(n,x) {I i=0,_n=(n);for(;it=t,z->r=r,mv(z->d,d,r);
   R z;}
  V1(iota){I n=*w->p;A z=ga(0,1,&n);DO(n,z->p[i]=i);R z;}
  V2(plus){I r=w->r,*d=w->d,n=tr(r,d);A z=ga(0,r,d);
   DO(n,z->p[i]=a->p[i]+w->p[i]);R z;}
  ...
1 - https://code.jsoftware.com/wiki/Essays/Incunabulum

Re: Let's Destroy C

#168
post #96

This just in: you can write bad code in any language. In this case, that language is the C Preprocessor, already well documented and widely accepted as a Bad Language To Start With. The title of the article is misleading: it's not "destroying C" it's writing Bad Code using the C Preprocessor. It's not destroying C any more than a series of bad puns destroys the English language.

> you can write bad code in any language. But it's more fun to do in C.

It’s much easier to do it in C, even when you think you’re not writing bad code.

Re: Let's Destroy C

#169

I've been a C programmer for several years now (out of necessity - C is still the best language for firmware and embedded development) There's been a lot of noise on the internet about Rust and C++20 and "modern" languages. I recently had an opportunity to try some of these first hand. Honestly the new language features are all terrible with few exceptions. In general, anything that was added to a language to support…

> I grew up as a programmer always thinking about the underlying CPU and the underlying memory and how my code would interact with both of them. It requires greater care as a programmer and tools like static analysers, code reviews and rigorous testing are extremely important.

And yet, even projects filled with extremely strong engineers who participate in all the best practices and run interprocedural static analysis and sophisticated fuzzers still write piles of security vulns in c programs.

Re: Let's Destroy C

#170
post #165

Earlier quoted context omitted.

> remove some of the undefined behaviors, There was a great talk from a C/C++ compiler writer about why you can't remove undefined behaviors while at the same time keeping C like speed. Simple example: accessing an array past it's end it's undefined behaviour. If you want to remove this, you need to add bounds checking (either to raise an error or to just return 0).

> There was a great talk from a C/C++ compiler writer about why you can't remove undefined behaviors while at the same time keeping C like speed. I don't think this is true. Look at Zig, they don't seem to have a problem removing a lot of C's undefined behaviour, while still being able to surpass C in speed in many cases. > Simple example: accessing an array past it's end it's undefined behaviour. If you want to remo…

> I think some undefined behaviour can also be detrimental to performance. If you pass two pointers to a function, and it's undefined whether they alias or not, there are optimisations you can't do.

I think this results from a misunderstanding of how undefined behaviour works in C. When a program exhibits undefined behaviour it is not a valid C program. The compiler may just assume (instead of having to prove) that it doesn't happen.

Example: the memcpy(3) standard library function. C says the behaviour is undefined if the given areas overlap. That means the implementation can perform optimizations "knowing" that there is no overlap. A valid C program can't possible invoke memcpy with buffers aliasing each other (because then, the program would be invalid). The compiler is not required to issue a diagnostic about these kinds of incorrect programs and just compiles your code assuming they don't exist.

Post reply on HN