neocity/language-criticism/c.jade

76 lines
4.2 KiB
Plaintext
Raw Normal View History

2021-03-08 17:07:44 +01:00
extends ../templates/main.jade
2021-03-10 19:49:56 +01:00
block title
| C | Language Criticism | xigoi
2021-03-08 17:07:44 +01:00
block content
2021-03-10 17:30:33 +01:00
h1 C Language Criticism
2021-03-16 23:00:36 +01:00
p.disclaimer I know that C was designed a long time ago when there wasn't much knowledge about language design. I'm not trying to berate its original creators, I just think it's time to move on to more modern systems programming languages like Nim, Rust or Zig. That's why this criticism is from a modern perspective.
p.notice I found
2021-03-08 17:07:44 +01:00
a(href="https://eev.ee/blog/2016/12/01/lets-stop-copying-c/") this article
2021-03-16 23:00:36 +01:00
| which explains many things much better than I, so please check it out. My article contains a few duplicates and some additional points.
2021-03-10 17:30:33 +01:00
h2 Preprocessor
2021-03-08 17:07:44 +01:00
p What's a better way of doing imports and macros than embedding another language with completely different syntax, which does naive text substitution, into your language? In order to avoid dangers which are not present in any sane import/macro systems, you have to do ugly hacks such as:
ul
li
p Include guards
2021-03-15 14:18:22 +01:00
pre
code.
#ifndef YOU_NEED_TO_MANUALLY_MAKE_SURE_THAT_YOUR_FILE_ISNT_INCLUDED_MULTIPLE_TIMES
#define YOU_NEED_TO_MANUALLY_MAKE_SURE_THAT_YOUR_FILE_ISNT_INCLUDED_MULTIPLE_TIMES
// your code here
#endif
2021-03-08 17:07:44 +01:00
li
2021-03-16 23:00:36 +01:00
p The
2021-03-08 17:07:44 +01:00
code do { ... } while (0)
| thing to make sure that a macro can be used as a normal function
li
p Wrapping everything in parentheses to make a macro work like a normal function
2021-03-15 14:18:22 +01:00
pre
code.
#define MAX(a, b) ((a) > (b) ? (a) : (b))
2021-03-08 17:07:44 +01:00
p If any parentheses are left out, it results in counter-intuitive behavior. Actually, even with them it doesn't work like a normal function: the arguments will be evaluated as many times as they're in the macro body!
2021-03-10 17:30:33 +01:00
h2 Braces & Semicolons
2021-03-16 23:00:36 +01:00
p See
2021-03-08 17:07:44 +01:00
a(href='braces-semicolons.html') Braces & Semicolons
2021-03-10 17:30:33 +01:00
h2 Syntax inconsistencies & warts
2021-03-08 17:07:44 +01:00
p Since many other languages (Java, C#, JavaScript, ...) have mindlessly copied most syntax from C, these mistakes have a profound effect on a whole family of languages.
ul
2021-03-16 23:00:36 +01:00
li All control structures that take a statement (if, while, for, switch) have the form of
2021-03-08 17:07:44 +01:00
code KEYWORD (SOMETHING) STATEMENT
| . Except for the do-while loop, which for some reason has the form
code KEYWORD STATEMENT KEYWORD (SOMETHING);
| . Totally different and including an extra semicolon.
ul.qa
2021-03-16 23:00:36 +01:00
li But it visually indicates that the condition is first checked after the statement!
li Then why is a for loop written as
2021-03-08 17:07:44 +01:00
code for (INIT; CONDITION; STEP) STATEMENT
| rather than
code for (INIT; CONDITION) STATEMENT (STEP);
| ? By the same logic, we should visually indicate that the step (usually increment) is first executed after the statement.
2021-03-16 23:00:36 +01:00
li The choice to require an if/while condition to be wrapped in parentheses, rather than requiring the body to be wrapped in braces (as in Rust). Not only does this introduce syntactic noise, but it leads to subtle bugs if you mess up indentation:
2021-03-15 14:18:22 +01:00
pre
code.
if (launch_button_pressed)
2021-03-16 23:00:36 +01:00
check(missile); /* this was added in after we decided to make our missile system safer */
2021-03-15 14:18:22 +01:00
launch(missile);
2021-03-16 23:00:36 +01:00
li The for loop is just another way to write a while loop, instead of something actually useful like Python's
2021-03-08 17:07:44 +01:00
code for item in items:
| .
2021-03-16 23:00:36 +01:00
li The syntax for labels (including switch cases) is completely different from everything else. For consistency, it could be something like
2021-03-08 17:07:44 +01:00
code label (NAME) STATEMENT
| and
code case (VALUE) STATEMENT
| .
2021-03-16 23:00:36 +01:00
h2 Tooling
ul
li By default, the compilers don't have most warnings enabled. And it's very difficult to actually enable all warnings.
code -Wall
| enables only some warnings. What the fuck?
2021-06-05 14:05:00 +02:00
li The default name for the compiled executable is
2021-03-16 23:00:36 +01:00
code a.out
| , instead of being based on the source filename. So you need to do things like
code gcc my_awesome_program.c -o my_awesome_program
| .
li You need to specify the libraries you're using in the compilation command, instead of just putting them in the source file.