PerranOakI support obiwanjecobi’s suggestion — cppreference is the most well prepared reference for C and C++ I have seen in my life. In particular it covers important topics, which are often ommited even from most books (perhaps because authors do not really understand them), like the strict aliasing rule.
If you are just doing this as a hobby, you may skip this post and just enjoy coding.
But beware: programming in C is like walking through a minefield. Programming in C without a copy of the latest standard at hand is like dancing drunk on a minefield under artillery fire. And I am not talking about the infamous manual memory management, buffer overflows and so on. The true trap is that intuitive interpretation of what a given C code does may wildly differ from what it actually does. It can catch anyone with their pants down. It even happens to seasoned programmers. To the point at which Linus Torvalds, the man behind Linux (the kernel), is blaming compilers for properly interpreting his code — properly in terms of what language defined, but not in the way he believed it works.
If you want to go professional — and especially if safety or security will depend on your code — be fully aware that you should dig into that hard to understand mess of specifications spread across 650 pages. If you can’t get a copy of the latest C standard — and I
do not suggest paying 180€ for it just to use the language — you may
legally download the latest standard draft from the working group. The draft is nearlyt he same as the final version. You may also consider reading Stack Overflow often, in particular things related to Undefined Behaviour.
Don’t be fooled into thinking that C is “close to bare metal”.
<justified-exaggeration> The only “bare metal” to which it is close is
PDP-11,
</justified-exaggeration> which is dead for over 30 years. Don’t assume that given code will have any specific representation in the compiled binary. In particular this may be a PITA on microcontrollers — through the years I’ve came across a few low-level constructs that are not reliably expressible with C. E.g. operations timing: while with proper code the compiler will not reorder operations like setting pins, it may reorder/move other operations, changing relative time at which setting pins occurs.
Finally, a nice and famous example of why C may be hell:
unsigned short a = 65535u;
unsigned short b;
b = a * a; // UB on some platforms! :DThe marked line is undefined behaviour on platforms with 16-bit
unsigned short and 32-bit
int. To make things more puzzling: the UB is caused by
signed overflow [sic! “signed”, not “unsigned”]. Compilers will likely convert that to code that does what most people would suspect it to do, but it is accidential.