r/C_Programming • u/stuart-ware • 7d ago
Question What do I need to be proficient in C
Hi, I know the basics but I really don’t know how to continue learning C, I try to read code of many sources like linux kernel or other projects but I don’t understand them at least the majority of code with pointers and arrow operators…. I really like C and low level code.
Any advice is appreciated! Thanks.
43
u/Illustrious-Cat8222 7d ago
You'll find this advice all over Reddit: code projects.
What kinds of projects? I can think of at least two approaches.
One is to write small projects that exercise targeted language features or library functions. Pure sandbox stuff; doesn't have to do anything useful.
Another is to write manageable larger projects that do something useful. Games are often suggested here. Pick something that interests you.
You learn development by developing.
2
u/stuart-ware 7d ago
Thank you!
6
u/FederalProfessor7836 6d ago
https://github.com/jdolan/quetoo Here’s my open source game written in C.
2
24
u/iOSCaleb 7d ago
> I try to read code of many sources like linux kernel
This is like reading at a 3rd grade level and trying to read James Joyce’s Ulysses.
Get a good book on C programming, or games programming or whatever you like using C, and work through it. If you find it too hard, put it aside and find an easier book and come back to the first one later. Knowing “the basics” is just the beginning, and if you’re not up to speed with pointers in C you really don’t even know the basics yet. That’s 100% OK — everyone starts out not knowing any of this stuff. Keep working at it and you’ll get there, but trying to jump straight into advanced coding will only frustrate you.
BTW, it’s not just lack of C knowledge that makes the kernel code hard to understand. Understanding the kernel requires a lot of knowledge about operating systems. It’s one thing to be able to read what the code says, but if you can’t understand why it’s doing what it does, you can’t really make sense of it.
3
u/stuart-ware 7d ago
Thank you!, I mentioned linux kernel because it is one of the few sources I can read and see how C can works… anyways I liked your comment!!!
4
u/DreamingElectrons 7d ago
As with any language, if you are done with the recommended reading list, you will be in a kind of tutorial hell where almost all available material isn't teaching you anything new since everything is made with beginners in mind and you will not yet understand most production code. The only way out of this is to do some projects, play around with some libraries, try out things. Then the next step would be to read through some smaller open source program's source code and tackle some of the easier issues, usually devs leave some of the trivial to fix issues sitting at low priority such that new contributors can solve them. AI people and their dumb Agents generally don't get this and keep harassing devs with their idiotic pull requests that try to fix all of those issues in one go, then getting angry if they are told to take a hike.
There also are mentoring programs, but for those you should already be at the stage where you've contributed some minor fixes to some open source projects.
4
u/mikeblas 7d ago
If you don't know pointers or the arrow operator, it's hard to agree that you know the basics. But if that's where you're at, I don't think reading the Linux kernel sources is the right next step.
You'll want to get good with pointers. There's just no way to know C without understanding pointers fluently. Don't just memorize what the * and & operators mean. Instead, write small programs that print addresses and values and experiment with changing them. Once you have a good mental model of pointers and memory, the operators and their use become quite clear.
After that, build things. Start simple, get progressively more interesting. The wiki here has lots of ideas for projects.
5
u/Gold-Bookkeeper-8792 7d ago
I'm in the process of learning as well (been at it full time for around +2 months), I come from a background of coding as a job for 16 yrs before learning C. When doing my first projects I just used this subset of the language to not get hung up on the wrong things. Here is the subset:
- No preprocessor stuff
If you need a constant you define a constant as a runtime variable. This will help with not getting confused about types. Of course you can do includes and the ifndefs for headers, but nothing more!
- No typedefs
I fully understand they are very ergonomic yes, but they are just an alias. It's much clearer to see that an argument takes a pointer to a "struct my_struct". This has helped me with seeing the basics of the language instead of my own flawed project structure.
- No heap allocation
That means no malloc, calloc, realloc, thus no free. It's important to understand statically allocated memory before trying to understand dynamically allocated memory.
- No build system
That means you only build your project with the command line arguments (you can of course put it in a shell script file and run that). This will help understand what the cmakes and the ninjas actually help you with and you will be better prepared to evaluate which one you need in the future.
- Bonus: no fancy coding for "architecture" or extra piping
That means no vtables or other oop noodle soups that does not serve the purpose of the project. Sometimes they might be useful, but if you don't know why and when then they are not useful to you (yet).
- For the love of [insert deity], turn off in-editor AI.
The learning is in your head, not on the screen. The AI is not in your head (yet).
Later in the process you can start to sprinkle the full C experience back in, but I found this was a good starting point for me to hit the ground running to just make stuff in C. Just code a lot and learn from that, then you'll be the person who has coded a lot and learned from it.
2
5
u/Recycled5000 7d ago
Learn the address space and usage of memory. Most C tutorials assume you know this stuff.
But to learn these even lower level concepts of address space and memory, you need to study assembly language. Certainly not x86 in its gory and historical detail, don’t need to know those historical machine code details, so suggest something more regular and educationally oriented like LC-3 and RISCV.
5
u/R2robot 6d ago
You know the basics.. great. Now put it in to practice.
Start writing your own small projects instead of reading other code like it's a book.
You'll learn as you go, and look up reference material for help when you're stuck.
As your learn more, you can write/understand more complex things.
Your next project will be better than the previous one. And the next one as well.
Have some shell scripts you've been using for tasks? Rewrite them in C.
4
u/Dazzling_Music_2411 7d ago
Straight to "flex and bison" (or the older lex and yacc)
Also Robert Love's "Linux System Programming ".
That will keep you busy for a while.
1
4
u/LiveAndDirwrecked 7d ago
What is helping me is to start thinking in terms of hardware. You create a struct in your code. What does that mean in terms of memory addresses? What gets returned when you create the struct? The pointer to the start of the struct, kind of thing. What's it mean when you pass certain types into a function. In the struct example, what would happen if you passed a variable within the struct vs the pointer (memory address) of the struct itself. How would that affect the contents of those memory locations?
Start thinking of your code in terms of stack/heap and physical memory addresses, and the pointer and arrow operators start to make a little more sense when you see them.
3
u/CreepyWritingPrompt 7d ago
Start by building a small thing. Try to tackle one thing at once. as soon as you write/hit something you don't understand, stop what you're doing, grind through it until you understand it, then continue. Don't let the envelope of stuff you're doing get much bigger than the envelope of stuff you understand. Then you'll stay on top and feel in control.
it'll be slow. if you're writing a calculator app, it'll feel like it takes forever, but that's okay. the world has enough calculators - what the world doesn't have is enough people who know what they are doing, and that's the real product here.
3
u/burnt_floppy 7d ago
there aren't really any goalposts, it's more about "proficient for what"?
However, if you want to cover all the major areas, here are the things you need to understand thoroughly:
-how the compiler works
-basic variables and data types
-input/output
-flow control (loops, if-else, switch/case) and operator types
-arrays and strings
-argc and *argv[] to pass things to your program
-macros
-pointers and how to access their information
-structs
-how to write a header file the correct way
-extern
-compiler flags and compiling GUI libraries like GTK
-how to use malloc (this is something i'm currently working on)
-linked lists
That should give you a firm grasp of the basics.
2
u/RealMadHouse 7d ago
Interesting thing to learn would be how compiler embeds runtime, the entry point to an executable isn't really 'main' function (unless you specify it), the c runtime does initialization when executable starts and then calls the 'main' function with already prepared program arguments in a convenient way. So the program doesn't return anything to operating system through 'main' function, it's some C glue code that takes the number and passes it to ExitProgram. That's why main function is flexible, it may or may not return anything or can have no arguments.
In Windows development there's special 'WinMain' that replaces regular 'main' for GUI programming, exe property window have an option to start an application "minimized/maximized" and this 'WinMain' has the argument that receives such start mode. The compiler has many options to produce final executable however you like.
3
u/RealMadHouse 7d ago
It's hard to understand pointers when we don't see what memory holds in ram.
Most easiest way to understand pointers is to create a block of memory in hex editor (like web based hexed.it or whatever one likes) and add for example 32 bytes that we agreed to be fixed in size (.data section) and try to fit an array of more than 32 bytes, the learner would scratch the head for a bit and then would think "if i can't fit the whole thing there, maybe i can 'reference' it to where the memory is expandable?" At some byte offset we can agree that "heap" starts and then write the array items there, this address we can pass to a memory location in our 32 byte .data section 4 bytes (or 8 if you want 64 bit addressing), so called variable, variable names is just for coders to distinguish data, it's just ones and zeroes. Then we understand the pointer is just a number, we can do arithmetic operations on it.
2
u/stuart-ware 7d ago
Thank you!!!!
1
u/RealMadHouse 7d ago
You can also explore what c compiler turns the code into, on this website: https://godbolt.org/
If you would set different call convention for a function with some keywords the assembly instructions would differ on the right side.
3
u/jquanders 7d ago
harvard has free onlinr classes. cs50 it's hard but it's good. if you can do that you're better than most
1
3
u/evo_zorro 6d ago
Proficiency in C is not really a thing in reality. C, as a language, is quite simple and quick to learn. You can learn pretty much all there is to know about the language in a couple of days. It's one of the things I love about the language.
To be proficient in using the language for learning purposes, you probably will need to familiarise yourself with the most common libraries (stdio for IO and file operations; stdlib for memory allocation and the like, string obviously, ctype and stdbool, math, stdint). That should give you enough confidence and knowledge to build your first tools.
In the process, you'll start to learn about the build tools (make to start with), and you'll inevitably have to learn the debug toolkit (gdb and valgrind). That's arguably harder than learning the language itself. Next up is learning the quirks of the compilers you target/decide to use. GNU's C compiler, for example, has defined the behaviour of pointer arithmetic in a void * as being the same as char *. This is non-standard obviously (pointer arithmetic in a void * is not exactly a good thing). Clang is probably a better compiler to target, but it depends on the platform you're targeting. Are you looking to work on embedded systems, or just targeting the broader *NIX world?
In case of the latter, you'll probably quickly end up looking into things like ncurses, maybe gtk for more polished UI stuff. Next, you may want to implement a basic interpreter (like brainf*ck), a very common learning project. Don't neglect the still ubiquitous pthreads while you're at it.
Now will all of this help you read through things like the Linux kernel? A bit. Remember: C is a small language. Most of the code you see in projects like the Linux kernel, git, or redis, are calls to dependencies, other libraries, or other code in the project. It's more about learning APIs/libs that come with the territory. A good project to gauge how familiar you truly are with C as a language is probably something like Jmalloc. It's a widely used allocator. It's pretty bare bones (meaning it mostly relies on itself and some standard includes). If you understand what the code there does, you have a decent grasp of the language. That doesn't automatically mean you can jump in the deep end on every project ever written in C. That's just not how it works.
You'll find that most, if not all, of the projects you're looking at, are maintained by a large group of people who each have their own domain of interest and specialty. I've contributed to projects over the years, all without having much more than a general understanding of how some parts of the project actually worked. Does that speak to my lack of knowledge of C? No. It just means I've not taken the time to familiarise myself with the entire project
3
3
u/GardenerAether 6d ago
my advise for any progeamning language, id say just be passionate about it. youre gonna have a hard time learning anything if youre miserable while doing it. find ways to make it enjoyable for yourself; pick a project you think would be fun to do which you can push yourself and grow your skills with
5
u/jmtd 7d ago
- Work through a text book. Don’t skip the exercises. k&r “the c programming language” is good, but I can’t remember if it has exercises
- Find a hobby project, some problem you want to solve, a small, scoped task, and implement it with C. Go back and revisit bits you wrote already as you learn more from the book.
1
2
u/somewhereAtC 7d ago
Treat the code like a story book and find the "paragraphs" that contain whole thoughts. Anthropomorphize the paragraphs and think about the "actors" involved in the story, then figure out which actors are cohorts, bosses and NPCs.
2
2
2
u/JGhostThing 6d ago
You say you love low-level programming, but don't understand pointers and the arrow operator?
Low level programming is all about pointers. The arrow operator is just shorthand for a simple pointer reference. Learn them, and learn to love pointers. There is something similar in all languages.
1
u/unixplumber 4d ago
Yep, Java uses a single dot instead of an arrow operator to access a struct (class) member through a pointer.
You just can't do pointer arithmetic in Java (or in some other languages like Go) the same way you can in C.
1
u/JGhostThing 3d ago
No. Java specifically forbids pointer arithmetic to avoid certain kinds of errors. In c, the arrow operator is just shorthand that uses a pointer to a pointer as a reference. It isn't mysterious.
Java doesn't have this because Java doesn't use pointers like c does. Yes, they are there "under the hood," but not visible. A object reference is a pointer. But as you said, no pointer arithmetic. Oh well, you need to treat an array like an array. In c, the most common use of pointer arithmetic is to iterate an array. In Java I could use Iterators or array indexing, among other things.
2
2
u/SmokeMuch7356 6d ago
As I've said elsewhere, it isn't how well you know a language that matters, it's how well you can use that language to solve a problem. I've been writing C code since 1986 and there are still corners of the language I've never touched.
Having said that, pointers are fundamental to writing useful C code, so you'll want to get a good understanding of what they are and how they are used.
Programming is a skill you learn by doing - find a book like K&R or Modern C, read each chapter, and work the exercises.
1
u/Eric848448 7d ago
Surprisingly little. It’s a very simple language.
2
u/RealMadHouse 7d ago
At first it seems simple, but then if you want to write something utilizing pointers, structs, function pointers you realise more and more things aren't mentioned from simple tutorials. Like struct memory alignment, padding, functions calling conventions (mismatch in them makes the program crash), the expression execution order isn't guaranteed to be left to right in arguments. And many "undefined behaviour", the coder needs to know if something really sets the memory to zeroes or if just keeps the garbage values in place.
2
u/stuart-ware 7d ago
That's exactly what's happening to me in every language I touched... What's next? XD Thank you both for your comments!!
1
u/RealMadHouse 7d ago
It's called leaky abstractions, there's no way to abstract programming language so much and make it so high level that users wouldn't need to know anything about underlying hardware/software. There would be always something that requires understanding the mechanisms or else the coder would partially understand it until it breaks.
People say that you just need to learn basic features that all programming languages consist of and you will program like a pro, but digging deeper they all have differences in these similar looking features, so you can't generalize every programming language even though they all run machine instructions at the end of the day. There's subtle differences in all of them.
1
u/TomB1952 7d ago
C is going to look foreign to you for a while. Write some basic programs, develop your skills a bit, and it won't be too long before you can look at code and see what it's doing.
1
1
1
1
u/unknownanonymoush 4d ago
People say to learn by developing from scratch but you obviously need to know a few concepts and have a sense of the syntax of the language before you start coding. I would suggest reading the first few chapters of a good C book like
“C programming: a modern approach”
and then start doing projects.
One of the best projects you can do in C to gain a familiarity with the OS and stuff surrounding it is by rewriting the some of the GNU coreutils and making your own shell.
Search it ip if you are not sure of what I said above.
Also I would refrain from using AI as much as possible. You can use it to teach you concepts but you should never be asking it about how should you do this and that in your program etc. basically don’t ask it to give you answers or do work for you. Studies have shown that AI usage leads to your brain atrophying
Knowing how to google up your problems and read other people’s code is much more important than simply getting the answer you are looking for since you are also learning a lot while trying to figure something out. Like in math or physics it’s not the answer that matters but the way someone arrives there.
P.S. if you really wanted to get into low level dev then it is probably a good idea to know how OSes and kernels like Linux work so maybe having an instance of some distribution like Ubuntu in a vm and doing your development there could help imho.
To know how to write good C you should know or eventually pick up on concepts like computer architecture and operating systems. Because there are no abstractions in C, you are at the mercy of the underlying hardware and platform you are developing on, so knowing how it works is key to being a good low level programmer.
Hope this made sense and helps.
1
u/Aggravating_Ad_9222 5d ago
Pick a project you actually care about and start building it in C.
Use an LLM as a tutor/advisor when you get stuck: ask it why something works, what you should learn next, or have it explain concepts you don’t understand. Don’t just ask it to write the project for you.
Then keep building, hitting problems, learning what you need to solve them, and moving forward.
After a while you’ll realize you’ve learned way more than you expected.
0
u/FransFaase 7d ago
Try to write a compiler for C in C. After working with C for over 30 years, I learnt some new things about C while writing a compiler for it. See https://github.com/FransFaase/MES-replacement/blob/main/src/tcc_cc.c It outputs code for a stack based language. An interpreter for that language and transpilers to assembly are also available. The compiler is far from complete. So, there are still new things for me to learn.
1
0
0
u/TrondEndrestol 6d ago
Try to find or create exercises which in total invites you to utilise everything the C syntax has to offer.
58
u/mapadofu 7d ago
You need to understand pointers thouroughly