I'm a C# guy who learnt C over the past 2 years. It absolutely made me a better programmer. I learnt by going through K&R first and then Expert C programming by Peter van der Linden. I also went through OS books, books that talk about the machines like Understanding the machine. I program in many high level languages. The main difference I felt when learning C is, I felt like I needed to learn how the machine actually works (what happens when we run a program) to really appreciate C. I continue to pursue this learning, these days I'm looking into embedded stuff.
Also look at C programs. I study old, small unix programs like "more".
I must also say that I see people asking about learning C on sites like Stack Overflow and getting discouraged saying that it's outdated and all. These people are doing a great disservice.
As C# guy who had to work with C for a while - this language is minefield.
If you want to create your own language and want to experience what choices are subpar by modern standards - C is way to go.
If I had choice then I'd pick Rust anytime when messing with low level programming.
I don't understand fascination with C just because it's "tradition" "everywhere" or "gives you full control" - especially that, since it brought us countless security issues
You'll wish you have decent C experience whenever you need to call an OS API directly; or whenever you need to write your own bindings to a library written in C.
PInvoke requires a working knowledge of C's concepts; you need to know the basics about pointers and how data is represented in order to do it correctly.
This statement comes from a lot of personal experience: I wrote a (currently closed source) adapter to call into SWMM from C#. (https://www.openswmm.org/SWMM51007/swmm5-c). (Hopefully I can open-source it at some point.)
In https://www.syncplicity.com/en, I wrote code in C# to interface with a closed-source driver to create a user-mode virtual disk drive. I also integrated with a different Virtual disk drive product that was written in C++ via PInvoke. I used PInvoke to create bindings between C# and Objective C for the Mac version as well.
First of all, most operating systems (and other lower-level APIs) you want to work with expose their APIs as C. These don't all have bindings in Rust. Even if you want to do them in Rust, you need to know enough C to be able to understand how to consume the API.
But then, there's plenty of legacy code in C. We aren't going to rewrite everything in Rust overnight.
More importantly, I think the "jury's still out" if Rust is better than C for embedded programming; or programming that's primarily direct memory manipulation. (And, if your embedded environment only gives you an API in C, you need to know enough C to write the API bindings for Rust before you can do embedded programming in Rust.)
Personally, I don't have any experience with unsafe Rust code. (I only do hobby projects in Rust.) In C# you can do C-style direct memory manipulation if you need to; but I'm not sure if Rust's "unsafe" is equivalent.
Also look at C programs. I study old, small unix programs like "more".
I must also say that I see people asking about learning C on sites like Stack Overflow and getting discouraged saying that it's outdated and all. These people are doing a great disservice.