I'm not sure if it's a praise for C though. Arcane design and lack of clarity might be fun to decipher, but it's not something that you'd want to see in the programming language.
Understanding pointers and pointer arithmetic is fundamental to understanding c. Most books and courses would spend a considerable amount of time and effort to make sure the student understands that. So 'arcane' is the wrong word I think.
You just need to get it, and really its no harder than, say context managers in python, or promises in js. Its not relevant at what 'level' those constructs are. They are novel in they way in which they model and solve real problems in context.
So 'lack of clarity' is really due to misunderstanding the context and problem space the langue was made to operate in.
I'm squinting very suspiciously at these comments suggesting this is about "pointer arithmetic". This is really about the little-used fact that you can have a "pointer to array of size N" type.
For hobby programming I work the minimalism of C, but then I also enjoy assembler. If I'm doing something more task-oriented then I prefer to use languages like js or python.
I don't mean here to compare different classes of languages. Even within systems programming languages, C has a lot of things that could be (and are) done better today.
What I meant is, that modern systems programming languages (like Rust for example) can avoid various issues by using all that was learned in programming languages design until today. C can't do that since it's stuck with its legacy requirements. This is quite an objective downside, and not just a matter of taste.
Name a language and someone will point out WTFs and subtle issues you might have never considered. The problem is the same when designing a language: computers think best with a large set of simple rules, humans think best with a small set of complicated rules, each having exceptions and different tiers of complexity for different levels of each developer's understanding.
I find C somewhat logical, but it has an easy-to-learn simplified version of itself that can be learned before re-reading the spec to complete your understanding of the language.
Sure, any language can have hard to understand parts or things that aren't designed the best way. But C is pretty old language. Creators of programming languages learned quite a lot since it was made, so they can avoid repeating known mistakes and can use newer design ideas. I.e. the quality of new languages can improve since they stand on the shoulders of giants.
>> humans think best with a small set of complicated rules
? I'd reword that to say humans are more entertained by a small set of complicated rules. Simple rules are easy for humans, but they can be boring.
However, in reality here, we're comparing apples to oranges. The instruction set for a computer is it's language. Asking a computer to speak English - that's our (humans') language, and with the tables turned, one could ask whether the computer thought better in English or Chinese, and the answer may be different but still meaningless.
Not all languages have equal wartiness. PHP and JavaScript are built on a swamp of inconsistencies whereas Haskell has a core axiomatic language. Scheme is fairly clean.
C evolved in a different age and is fraught with undefined behavior.