r/cprogramming

A tiny, single-header C library to track true RAM usage on Linux

Working in C lately made me realize there is no drag and drop way to measure true ram usage, because when you ask the OS it will give you whatever your program is using PLUS the shared libraries, so if your code is actually being executed in a few kb of memory it may seem like it's megabytes simply because there is no clean way to ask for the true RAM usage. I looked for a drag and drop library where I could just drop an .h file into my project and get the proportional set size and be able to monitor this, but I could not find anything lightweight and dependency-free. So I wrote this library, which is literally a library for true ram usage, hence the libtrm name.

The way this works is, I just made an ASCII parser to rip the data directly from the /proc files in the kernel. It tries to use the modern smaps_rollup fast path but automatically falls back to parsing the full smaps for older Linux kernels from before 2017, in case someone still uses that. You can then use really simple calls to that data to log them at any point in your program. I used kilobytes and bytes since, you know, this is C. You can also diff how much RAM usage the OS was reporting against what you truly used.

I also included a main.c that acts as an interactive tutorial. It runs a stress test shows how PSS barely moves when you malloc(), but spikes the second you actually memset() data into it. I encourage you to tinker with it, it makes it easier to understand the commands.

I am happy with how lean it turned out. It is perfect for developers who want to add a live RAM display to their tools without adding overhead. Feedback on the parser logic is appreciated.

Web: https://www.willmanstoolbox.com/libtrm/

Repo: https://github.com/willmanstoolbox/libtrm

reddit.com
u/JellyGrimm — 9 hours ago
▲ 1 r/cprogramming+1 crossposts

should I be following abdul bari's "Mastering Data Structures & Algorithms using C and C++" on udemy? or please recommend a good source which would suffice college exams and would also help in placement preps.

so, I have quite a good grasp on C programming. I want to start dsa next. I am not quite sure what resource to follow. Abdul Bari's course looks good. I'm confused.

also please recommend some good books for dsa.

reddit.com
u/Cool_Assist_264 — 1 day ago

My opinions about code style

I disagree with most people about code style.

In code that is just for myself, I actively avoid structs, unions, pointers, floating point numbers, dynamic memory allocation, for loops, threading, typedefs, and most of the standard library. The reason is that I strongly dislike debugging, and I would rather spend more time writing code and less time debugging it. Additionally, I compile with many warning flags that are not included in the common -Wall -Wextra -Wpedantic.

Furthermore, I litter code that is just for myself with a macro that is almost like assert, yet instead of expanding to nothing if NDEBUG is defined, it expands to nothing if EBUG is not defined. That enables me to pass -DEBUG to GCC to compile a debug build. Since the macro expands to nothing when EBUG is not defined, there is no penalty for optimized builds. Since I do not use "debuggers", -Og is not needed for a debug build of code that is only for me.

Additionally, I limit myself to C89 (aka C90) whenever I am working on something small for myself. (I use the -ansi and -Wpedantic GCC flags to help enforce this.) The reason is that I simply do not find the vast majority of the features introduced since then to be useful.

I figure that if I am not going to use any of the features anyway, then it is probably a mistake if I do accidentally use one. Once a program gets large enough, then I may eventually find myself wanting to use a newer feature, like long long, restrict, _Noreturn, etc. However, I use C89 unless I have a reason not to.

Honestly, although no-one seems to agree with me on this, I find global variables to be significantly better than passing massive structs and many pointers around the place, like most people do. In my own experience, I have found myself to make fewer mistakes when working with global variables than when working with structs and pointers, even when the structs are kept small. Another thing that I find to be an absolute non-problem is goto statements. I prefer using goto statements over sacrificing maintainability by having a mess of if statements and and extra variables, which is sometimes needed if you are dogmatically insisting on avoiding a goto statement.

I like to declare function parameters const, including scalars, and I like to have functions return only at the end. If I feel the need to have another exit point, and the code is for myself, then I will typically use a goto statement with a label at the end (and possibly a null statement if the function is void and I am using C89). I do this because it is easier to refactor code when the parameters are const and there is a single exit point.

When comparing things, I always use < and >=, yet never > or <=. The reason is that it is trivial to replace one direction of a comparison with the other, and < is not likely to be confused with >=, because they point opposite directions.

I dislike small functions. I prefer medium sized functions. The reason is that I find that having many functions makes it more difficult to mentally understand the control flow of a piece of a program. If a function is less than a screen of text, then I probably consider it to be too small. Having large functions can make it more difficult, as well, due to deep nesting. Thus, a happy medium is the best.

I avoid storing boolean values into variables or passing them to functions. If it is annoying to avoid them, then I refactor my code. Also, if an integer fits in a `signed char` or an `unsigned char`, then I will use store it as that, even if it slightly hurts performance in some cases. If an integer is never negative, then I will store it as an unsigned integer, even if it slightly hurts performance in some cases.

Another thing that I disagree with most people about is error handling. When writing code that is only for myself, I typically handle errors by calling exit(1);and printing a message if it is a debug build (EBUG). Most other people think that this is insane. However, I find that it reduces debugging time.

I use either astyle with a configuration file or GNU indent with -kr to format my code, and I use cppcheck with --enable=all to lint my code.

When working on something that compiles reasonably quickly, I compile my code frequently when making changes to ensure that it still works on basic cases, so that I do not need to spend as much time trying to figure out what change broke the code. However, if the code compiles slowly, then I do not compile frequently.

I do not use version control when working on something that is only a few files. Instead, I occasionally make a backup file of a known working version of whatever file I am working on. I never use "debuggers" when debugging. I do not find debuggers to be useful, ever. However, I use valgrind, and I have found it to be useful, even though it makes code run very slowly during debugging.

Another thing that I disagree with many people on is that I think that fewer larger files is often more easily understood than a large amount of tiny files.

Unfortunately, when I am working on code that is not just for myself, I do not always have a choice about stylistic choices, and I am sometimes forced to do dumb things like pass massive structs everywhere and use malloc to allocate space for an array that has a size that is a compile time constant. Furthermore, attempting to compile code that is not written by me with all of the warnings and lints that I prefer yields so many warnings that it is not remotely worth fixing. In addition, the code quality of the code that I write often degrades by a large amount when I am trying to meet a deadline, because the short term is prioritized over the long term.

reddit.com
u/ElementWiseBitCast — 3 days ago
▲ 9 r/cprogramming+1 crossposts

Making a port of Inquirer.js to C

Hello, recently i started porting Inquirer.js to C, cause i needed a simple but good-looking TUI, i only implemented A Text input for now, but is cross-platform (Windows, Posix, Unix), i know it isn't much but i wanted to hear some feedback! P.S. I'm only 15 and still going to School, so i do not expect this to be used much

github.com
u/F3lix550 — 3 days ago

C Programming certification

Hello,

I am trying to find a website to get a C language certification.
I just want to get the basic knowledge of the language and have a certification to increase my chances to get into a master's degree (which is unrelated to programming but knowing some computer languages can get you a better score).

reddit.com
u/Ok_Expression1248 — 4 days ago
▲ 3 r/cprogramming+2 crossposts

Struggling to compile legacy AVR project (CodeVisionAVR 2.03 → latest version) – binary size issue

Hey everyone,

I’m working on a legacy AVR project that hasn’t been touched in years, and I’ve hit a blocker.

The project was last successfully compiled around 2008 using CodeVisionAVR v2.03

I now have the full codebase and tried building it using the latest CodeVisionAVR

I fixed a few minor linking issues, but the final binary exceeds the flash size of the target MCU

I already tried removing debug prints and adjusting optimization levels, but no improvement

To troubleshoot further, I even set up a Windows XP VM to try building with the original toolchain (v2.03), but I’m stuck there as well due to licensing issues.

If anyone has any idea to bypass the license or if you have a cracked version. Please let me know it'll be very helpful to me.

reddit.com
u/LandscapeFar4925 — 19 hours ago

I wrote an article on how to fake real classes in pure C without using C++

I just published an article that turned into one of the most interesting things I have written in a while.

The idea is simple but fun: how do you get class-like behavior in pure C, without using C++ at all?

C is usually seen as a very low-level, direct language. That is exactly why I liked digging into this. I wanted to show that even in plain C, you can still build something that feels a lot more structured and object-oriented if you understand the language well enough.

In the article, I break down one simple trick that makes this possible and explain it in a practical way, not just as a theory dump. If you enjoy C, systems programming, or just like seeing old-school languages do clever things, you might find it interesting.

Article is attached in the comment.

I would genuinely love feedback from people who work with C or have tried similar approaches. What do you think about using this kind of pattern in real projects? Would you use it, or avoid it and keep things more traditional?

levelup.gitconnected.com
u/abhijith1203 — 5 days ago
▲ 6 r/cprogramming+1 crossposts

Getting Zed and Clangd to Be Useful for the Retro Programmer

Hope this helps someone: I wrote a blog post about how with Zed and a .clangd configuration file you can transform a hostile language server into a useful assistant. The defining properties are that it accepts non-standard calling conventions with -Wno-ignored-attributes, accepts the Watcom dialect with -fms-extensions, preserves includes hidden behind assembly with // IWYU pragma: keep, and - most importantly - lets you keep code completion.

reddit.com
u/ifknot — 3 days ago

Weird shift expression result

This code outputs what I believe are the wrong results in 3 of the 4 cases. I think the upper 8 bits of the uint16_t should be always 0, because the shifts should occur on uint8_t and only the result should be cast to (uint16_t).

Why am I wrong?

/* Compile: gcc sol.c main.c -o prog && ./prog <1-4> */
#include <stdio.h>
#include <stdint.h>

/* byte:    An 8-bit input
   returns: An 8-bit value (returned as uint16_t) where the high 4 bits
            and low 4 bits of byte are swapped
   Example: swap_nibbles(0xF0) returns 0x0F
*/
uint16_t swap_nibbles(uint8_t byte) {
    return (uint16_t)((byte << 4) | (byte >> 4));
}


void test1(void) {
    uint8_t b = 0xF0;
    uint16_t r = swap_nibbles(b);
    printf("Result: 0x%04X\n", r);
}

void test2(void) {
    uint8_t b = 0xA2;
    uint16_t r = swap_nibbles(b);
    printf("Result: 0x%04X\n", r);
}

void test3(void) {
    uint8_t b = 0x00;
    uint16_t r = swap_nibbles(b);
    printf("Result: 0x%04X\n", r);
}

void test4(void) {
    uint8_t b = 0xFF;
    uint16_t r = swap_nibbles(b);
    printf("Result: 0x%04X\n", r);
}

int main(int argc, char **argv) {
    if (argc < 2) {
        printf("Usage: %s <1-4>\n", argv[0]);
        return 1;
    }
    int t = argv[1][0] - '0';
    switch (t) {
        case 1: test1(); break;
        case 2: test2(); break;
        case 3: test3(); break;
        case 4: test4(); break;
        default: printf("Invalid test. Use 1-4.\n"); return 1;
    }
    return 0;
}

outputs

❯ ./main 1
Result: 0x0F0F
❯ ./main 2
Result: 0x0A2A
❯ ./main 3
Result: 0x0000
❯ ./main 4
Result: 0x0FFF
reddit.com
u/cryptofakir — 6 days ago

How would I write my own compiler from scratch?

The language I have mainly used is Python because it is the language we use at sixth form but over summer I'd like to learn C or assembly. I have read books on how computers physically work and I have a decent intuition on how machine code is actually processed by the CPU. My end goal is to have enough knowledge of computer programming to be able to write my own compiler and my own programs. I feel that I would like to write a compiler in assembly, even if its a really simple compiler, I just want to be able to know the fundamentals about how compilers work, I'm not really bothered about it being very optimised as long as it works properly. I plan to first read a book on C to try to become comfortable with the language. I plan to read "The C programming language" by Dennis Ritchie and Brian Kernighan. I have programmed a bit in C from a book which I borrowed and it seems like it makes sense. I would just like some advice on what I should know before planning on writing my own complier from scratch.

reddit.com
u/Relevant_Bowler7077 — 7 days ago

I built a zero-dependency, self-hosting C/C++ build system configured entirely in C (Loom)

Hey r/cprogramming!

I've been working on a project called Loom, and I'd love to share it and get some feedback from the community. Basically it's a cross-platform C/C++ build system that is fully self-hosting, requires zero external dependencies, and uses pure C11 for its build configurations (build.c).

I built this because I was frustrated with CMake's bizarre syntax and having to learn complex new Domain Specific Languages (DSLs) or wrestling with Makefiles just to compile my C projects. I figured: if I'm writing C code, why not configure the build pipeline dynamically using a clean C API?

Here's the repository link, feel free to contribute, I'll be looking for more ways to improve the project.

Key Features

  • "Configuration as code" (inspired by build.zig): You define your build targets using a clean, readable API in a build.c file. You get all the benefits of C (macros, variables, logic) with none of the typical CMake friction.
  • Zero-dependency and self-hosting: Written in strictly standard C11. Loom is capable of fully compiling and rebuilding itself perfectly.
  • Truly cross-platform (native windows): It runs natively on macOS, Linux, FreeBSD, and Windows. I recently finished a complete Windows port where it leverages raw Win32 APIs (like CreateProcessA, FindFirstFileA) instead of relying on slow POSIX emulation layers like Cygwin or MSYS2.
  • Fast and incremental: Features intelligent dependency tracking (parsing depfiles and using file hashes) so it only recompiles what actually changed. It also auto-detects your logical CPU cores and compiles asynchronously in parallel.
  • Batteries included:
    • Build Executables, Static Libraries (.a/.lib), and Shared Libraries (.so/.dll).
    • Built-in wildcard/recursive globbing (add_glob) to just throw a directory of sources at it.
    • Direct pkg-config integration (link_system_library).
    • Instant project scaffolding (loom init).

Example build.c

Here is what it looks like to configure a modern C project:

#include <loom.h>

void build(loom_build_t *b) {
    loom_target_t *exe = add_executable(b, "my_awesome_app");
    
    add_glob(exe, "src/*.c");
    add_include_dir(exe, "include");
    
    set_standard(exe, LOOM_C11);
    set_optimization(exe, LOOM_OPT_RELEASE_FAST);
    
    link_system_library(exe, "raylib");
}

Building this project from scratch has taught me an incredible amount about platform-specific process abstractions, caching logic, and avoiding standard POSIX traps on Windows.

I would love to hear your thoughts, feedback, or any critique on the codebase architecture! Let me know what you think.

u/sisoyeliot — 9 days ago

Tx - Small, C text editor

Hi all!

Recently been working on a personal project to improve my C programming skills. From initially following the Kilo text editor project, I decided to grow the editor into a modal, vim - like editor. I had a lot of fun doing this project and learned a lot! Would love some feedback and any thoughts or opinions.

Thanks!

https://github.com/BitsBob/tx/

u/radio_hx — 9 days ago
🔥 Hot ▲ 73 r/cprogramming

tip - do not name variables like libc functions

Today I spent three hours debugging why ncurses jumped to address 0x55d9f367b4c0 out of the wild and crashing when calling stat...

I had a variable named stat holding the status of the program, and it was doing some really shitty and incorrect pointer arit on stat or something.

so yeah, just a quick tip :)

reddit.com
u/Key_River7180 — 12 days ago

Scanf

mi pregunta raida en porque casi nunca salen tutos en youtube que expliquen como usar scanf realmente como su valor de retorno o parametros de control, y no hablan del buffer que deja y como solucionarlo, a diferencia de solo decir "es mala practica usar scanf" y te aseguro que si preguntas el porque solo te diran que despues de un espacio no lee mas y lo deja en el buffer huerfano, y causa errores si no se prevee

reddit.com
u/pruebax11 — 9 days ago

I built a terminal-based interactive DSA library in C (~4000 lines) — the graph chapter nearly broke me, here's why

Project: full DSA library in C, terminal-based and interactive. Linked lists (singly, doubly, circular), stacks, queues, BST with traversals, graphs (adjacency matrix + adjacency list, DFS/BFS), infix-to-postfix + postfix evaluation, hashing, sorting, searching. Manual memory management throughout, Valgrind-clean.

GitHub: https://github.com/darshan2456/C_DSA_interactive_suite

The linked list and tree chapters were hard but survivable. Linked list reversal in-place taught me pointer discipline the hard way — silent heap corruption from one misplaced assignment is a very effective teacher. BST traversals broke and then permanently fixed my mental model of the call stack during recursion.

The infix-to-postfix chapter was different — not painful, but it's where I first understood what composing abstractions actually means in practice. I didn't use a standalone stack. I built a stack on top of my linked list implementation, then used that stack to implement the Shunting Yard algorithm. So the call chain was: algorithm → stack operations → linked list pointer manipulation — all code I wrote, all the way down. When it worked, I could trace exactly why it worked at every layer. That kind of end-to-end ownership over your abstractions doesn't happen when a language hands them to you.

But the graph chapter was a different category of hard entirely, specifically adjacency list representation.

Adjacency matrix is clean — a 2D array, index by vertex, done. I was comfortable.

Then adjacency list: conceptually it's just each vertex storing a list of its neighbors. Simple enough. In C it means an array of linked lists, where each list is dynamically allocated and grown independently. Suddenly you have:

- `struct Node** adjList` — a pointer to an array of pointers to linked list heads

- dynamic allocation for every single edge insertion

- pointer-to-pointer manipulation for list insertions

- freeing a graph means iterating every list, freeing every node, then freeing the array itself — in the right order

And the edge cases multiply fast. What happens when you insert a duplicate edge? What if the vertex index is out of bounds? What does a partial free look like when malloc fails halfway through building a graph?

It also made the complexity tradeoff concrete in a way Big-O notation alone never did. O(V²) space and traversal on a sparse adjacency matrix isn't just inefficient on paper — you feel it when you've implemented both.

Feedback on the implementation very welcome — especially around the graph memory management and whether my adjList structure could be cleaner.

u/Straight_Coffee2028 — 11 days ago

subreddit focused on ncurses library.

I didn't find any sub about it, so I created it. If you have some project that uses ncurses, feel free to post in r/ncurses_h. The goal is just to create a dump of ncurses stuff for info and inspiration.

I think a lot of C programmers use it for graphics, so I'm posting here.

reddit.com
u/Maleficent_Bee196 — 11 days ago

Optimizing Chained strcmp Calls for Speed and Clarity - From memcmp and bloom filters to 4CC encoding for small fixed-length string comparisons

I've been working on an article to describe a small performance issues with a pattern I've seen multiple times - long chain of if statements based on strcmp. This is the equivalent of switch/case on string (which is not supported in C).

bool model_ccy_lookup(const char *s, int asof, struct model_param *param)
{
    // Major Currencies
    if ( strcmp(s, "USD") == 0 || strcmp(s, "EUR") == 0 || ...) {
        ...
    // Asia-Core
    } else if ( strcmp(s, "CNY") == 0 || strcmp(s, "HKD") == 0 || ... ) {
        ...
    } else if ( ... ) {
        ...
    } else {
        ...
    }
} 

The code couldn’t be refactored into a different structure (for non-technical reasons), so I had to explore few approaches to keep the existing structure - without rewrite/reshape of the logic. I tried few tings - like memcmp, small filters, and eventually packing the strings into 32-bit values (“4CC”-style) and letting the compiler work with integer compares.

Sharing in the hope that other readers may find the ideas/process useful.

The article is on Medium (no paywall): Optimizing Chained strcmp Calls for Speed and Clarity.

I’m also trying a slightly different writing style than usual - a bit more narrative, focusing on the path (including the dead ends), not just the final result.

If you have a few minutes, I’d really appreciate feedback on two things:

  • Does the technical content hold up?
  • Is the presentation clear, or does it feel too long / indirect?

Interested to hear on other ideas/approach for this problem as well.

medium.com
u/Yairlenga — 9 days ago
▲ 21 r/cprogramming+1 crossposts

Optimizing linked list to have O(1) time complexity for appending at tail.

So came across a nice trick where you hide some metadata before the actual DS and then while doing operations you just retrieve the meta data and do task more efficiently .

So i defined a struct at the start of linkedlist and have count and the pointer to last node stored there and whenever I needed to append I just got the last node pointer from there and just update it.

So i guess a small optimization.

But I really enjoyed this putting hidden data and working with it.
I think it's super cool, do you guys also find it cool ?

Here is the data structure and initializing function I implemented.

\

typedef struct Header {

int count;

struct Node* LastElement;

} Header;

typedef struct Node {

int value;

struct Node* next;

} Node;

Node* createFirstNode(int value) {

Header* header = (Header*)malloc(sizeof(Node) + sizeof(Header));

if(header == NULL) {

printf("Error: Memory allocation failed");

exit(1);

}

header->count = 1;

Node* newNode = (Node *)(header + 1);

newNode->value = value;

newNode->next = NULL;

header->LastElement = (Node *)(header + 1);

return newNode;

}

\

It's probably not the best way or even standard way but when I started implementing it i didn't really think much further ahead and just kind of did it and when complications occurred I just coped harder.

Don't look too hard in how it will just break if someone passed mid node or how i should have implemented opaque struct or whatever.

Cool trick right eh eh eh!!

reddit.com
u/souls-syntax — 1 month ago

Came across this on cbsecommerce

​

I came across a website that is used by CBSE teachers to check osm but honestly the design looks AI-generated

Someone mentioned that it might be “easily hackable” if you have strong knowledge of systems like Red Hat/Linux, but that sounded a bit overstated to me.

I’m not trying to hack anything 🥀🥲 just understand from a cybersecurity view

- What actually makes a website “easy to hack”?

- Can you judge security just from how a site looks?

- What are common vulnerabilities in poorly built educational/government-type sites?

Would appreciate insights from people who understand.

reddit.com
u/moongotsun — 1 hour ago