5 ms·
C is simple. Representing computation as words of a fixed bit length, in random access memory, is not (See The Art of Computer Programming). And the extent to
by grandempire 2y ago
C is simple.
Representing computation as words of a fixed bit length, in random access memory, is not (See The Art of Computer Programming). And the extent to which other languages simplify is creating simpler memory models.
- mort96 2y agoWhat about C is simple? Its syntax is certainly not simple, it's hard to grok and hard to implement parsers for, and parsing depends on semantic analysis. Its macro system is certainly not simple; implementing a C preprocessor is a huge job in itself, it's much more complex than what appears to be necessary for a macro system or even general text processor. Its semantics are not simple, with complex aliasing rules which just exist as a hacky trade-off between programming flexibility and optimizer implementer freedom. C forces programs to be simple, because C doesn't offer ways to build powerful abstractions. And as an occasional C programmer, I enjoy that about it. But I don't think it's simple, certainly not from an implementer's perspective.
- grandempire 2y agoEach of these elements is even worse in every other language I can think of. What language do you think is simple in comparison?
- mort96 2y agoGo, Rust, Zig? I'm curious, what language do you know of with a more complex macro system than the whole C preprocessor? EDIT: To be clear to prospective downvoters, I'm not just throwing these languages out because they're hype or whatever. They all have a grammar that's much simpler to parse. Notably, you can construct a parse tree without a semantic analyser which is capable of running in lockstep with the parser to provide semantic information to the parser. You can just write a parser which makes a parse tree.
- unclad5968 2y agoI've never written a parser for any of those languages but my intuition is that Go is easier to parse than C. The others are debatable. Rust macros are definitely not simpler than C macros. I'm not sure what could be simpler than text substition. Zig doesn't have macros and comptime is implemented as a language VM that runs as a compilation step(last I knew), so that's definitely not simpler. I don't use go often, but I don't think it has macros at all so that's definitely simpler. When people say that C is a simple language, my interpretation is that they mean it is easy to interpret what a C program does at a low level, not that it is simple to write.
- mort96 2y agoThe other languages can be written by a parser. A parser for C needs a semantic analyzer working in tandem. The C preprocessor is not text substitution. It is not easy to describe what C does at a low level. There are simple, easy to describe and wrong models of what C does "at a low level". C's semantics are defined by a very difficult to understand standards document, and if you use one of those simple and enticing mental models, you will end up with incorrect C code which works until you try a different compiler or enable optimisations.
- unclad5968 2y agoBy that argument the other languages mentioned are impossible to understand since they don't have a spec, except for Go again.
- mort96 2y agoNo. The other languages have documented semantics too. Just happens that C's are in the shape of a standards document.
- uecker 2y agoA parser for C does not need a semantic analyzer. What C does it allows semantic analysis to be integrated into the parser. The preprocessor has some weird behavior, it it is also not very complicated. And I would argue that the abstract machine model of C is still relatively simple. There are are certainly simpler languages in this regard, but they give up one of the key powers of C, i.e. that you can manipulate the representation of objects on a byte level.
- csb6 2y agoPascal (and most other Wirth languages) is better in most of these respects than C. Of course there are other flaws with Pascal (cf “Why Pascal is not my favorite programming language”), but it proves that C has a lot of accidental complexity in its design.
- grandempire 2y agoI agree pascal is simpler - but pascal also simplifies the memory model.
- pjc50 2y agoParsing isn't too bad compared to, say, Perl. The preprocessor is a classic example of simplicity in the wrong direction: it's simple to implement, and pretty simple to describe, but when actually using it you have to deal with complexity like argument multiple evaluations. The semantics are a disaster ("undefined behavior").
- mort96 2y agoI would probably describe Perl as really complex to parse as well if I knew enough about it. Both are difficult to parse compared to languages with more "modern sensibilities" like Go and Rust, with their nice mostly context free grammars which can be parsed without terrible lexer hacks and separately from semantic analysis. Walter Bright (who, among other things, has been employed to work on a C preprocessor) seems to disagree that the C preprocessor is simple to implement: https://news.ycombinator.com/item?id=20890749 https://news.ycombinator.com/item?id=20890749 > The preprocessor is fiendishly tricky to write. [...] I had to scrap mine and reimplement it 3 times. I have seen other people in the general "C implementer/standards community" complain about it as well.
- kibwen 2y ago> Parsing isn't too bad compared to, say, Perl. This is damning with faint praise. Perl is undecidable to parse! Even if C isn't as bad as Perl, it's still bad enough that there's an entire Wikipedia article devoted to how bad it is: https://en.wikipedia.org/wiki/Lexer_hack https://en.wikipedia.org/wiki/Lexer_hack
- uecker 2y agoFirst (as in my other comment), the idea that C parsing depends on semantic analysis is wrong (and yes, I wrote C parsers). There are issues which may make implementing C parsers hard if you are not aware of them, but those issues hardly compare to the complexities of other languages, and can easily be dealt with if you know about then. Many people implemented C parsers. The idea that C does not offer ways to build powerful abstractions is also wrong in my opinion. It basically allows the same abstractions as other languages, but it does not provide as much syntactic sugar. Whether this syntactic sugar really helps or whether it obscures semantics is up to debate. In my opinion (having programmed a lot more C++ in the past), it does not and C is better for building complex applications than C++. I build very complex applications in C myself and some of the most successful software projects were build using C. I find it easier to understand complex applications written in C than in other languages, and I also find it easier to refactor C code which is messed up compared to untangling the mess you can create with other languages. I admit that some people might find it helpful to have the syntactic sugar as help for building abstractions. In C you need to know how to build abstractions yourself based on training or experience. I see a lot of negativity towards C in recent years, which go against clear evidence, e.g. "you can not build abstractions" or "all C programs segfault all the time" when in reality most of the programs I rely on on a daily basis and which in my experience never crash are written in C.
- mort96 2y agoHuh? How are you supposed to parse a statement like 'x * y;' without some form of semantic analysis? You need to be able to look up whether 'x' has been declared as a variable or a type, and parse it as either a multiplication expression or a variable declaration. Am I wrong on this?
- uecker 2y agoTrue. But this does not require full semantic analysis, it only requires distinguishing between typedef names and other identifiers. You can argue that this part of semantic analysis, but this would be rather pedantic. Tracking this could equally seen as part of parsing.