<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Gazel-create</title>
    <description>The latest articles on DEV Community by Gazel-create (@gazel-create).</description>
    <link>https://dev.to/gazel-create</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4101124%2F3310ea16-8fd8-4cd9-9970-f94adc86a12d.png</url>
      <title>DEV Community: Gazel-create</title>
      <link>https://dev.to/gazel-create</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gazel-create"/>
    <language>en</language>
    <item>
      <title>Free-Up-The-Space (Part-3)</title>
      <dc:creator>Gazel-create</dc:creator>
      <pubDate>Wed, 30 Sep 2026 08:21:47 +0000</pubDate>
      <link>https://dev.to/gazel-create/free-up-the-space-part-3-3ajk</link>
      <guid>https://dev.to/gazel-create/free-up-the-space-part-3-3ajk</guid>
      <description>&lt;p&gt;This is Part 3 of my series on memory allocation. I kept having this recurring feeling that I did not add a function to free up the memory after use, which has led me to this article. Additionally, an excellent lunch on Monday afternoon acted as a catalyst that brought this article into being. I was not planning on writing this, but Sir Casper accused me of using AI for writing my articles (Yes, I use it, but only for proofreading and grammar). Therefore, I have undertaken this assignment not to prove him wrong, but as a fun escapade of life.&lt;/p&gt;

&lt;p&gt;There will be no breakthroughs or eureka moments here, just an accumulation of mechanics with fundamental ideas of how to work with memory inside RAM. I am working with virtual memory, so please keep that in mind.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pointer Arithmetic
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;user_space&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;metadata2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;metadata3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)((&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;user_space&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;request_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The lovely code above is a wonderful way to understand pointer arithmetic. I will be pasting my whole code below, so please look at it if you get confused. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;void * user_space&lt;/strong&gt;&lt;br&gt;
Here, I have created a pointer of type void, which literally means the data type has not been defined yet. If you are wondering how the OS deals with it, just know it is read as a marker that says the type will be defined later, and the OS moves on. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(void *)(metadata2 + 1);&lt;/strong&gt;&lt;br&gt;
As we can see in our code, we have a data type struct named metadata, and we created a variable named metadata2 of type struct metadata. So, if the data type is struct metadata, how is it possible that we can do + 1? Isn't 1 an integer? Also, we cannot add integers to a struct, pointer, boolean, or array. So, what are we doing here?&lt;/p&gt;

&lt;p&gt;First, we need to understand what metadata2 is: it is a struct of 24 bytes. How? Look at this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;memory_size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;is_free&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;size_t is for an unsigned integer whose data size changes according to the architecture; for x86 64-bit, it is 8 bytes. bool here is 1 byte. We only need 1 bit to store 0 or 1, but because computer memory is mapped out in 8-bit blocks (byte-addressable), the smallest piece of memory we can ask for is 1 byte.&lt;/p&gt;

&lt;p&gt;Finally, we have a pointer inside the struct, which is always 8 bytes. Because all these programs are running on a 64-bit architecture, the CPU processes data in 64-bit (8-byte) chunks, and memory addresses themselves are 64 bits wide. This creates a theoretical maximum memory size range of 0 bytes to 16 exabytes (EB) (specifically 2^64 bytes, which equals 18,446,744,073,709,551,616 bytes). These spaces are divided into 2 ranges: User-Space and Kernel-Space. In typical systems, the Virtual Memory is addressed using a 2^48 bit range.&lt;/p&gt;

&lt;p&gt;What all this means is that in our 8-byte addressable system, the CPU finds it easier to deal with 8 bytes at a time. Hence, padding is used to make each field of the memory stack exactly 8 bytes, so 8 x 3 = 24 bytes for our struct.&lt;/p&gt;

&lt;p&gt;In turn, when we see metadata2 + 1, we need to understand that metadata2 is actually 24 bytes. It is a struct located inside the raw_memory&lt;br&gt;
&lt;code&gt;void * raw_memory = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);&lt;/code&gt;&lt;br&gt;
where each block is sized by our 24-byte struct. Hence, when we do + 1 arithmetic, we get a jump of 24 bytes instead of just 1. If we had converted it to (char *), then we could have gotten a 1-byte jump, but we are looking at it pretending it's a struct metadata of 24 bytes located inside the raw_memory.&lt;br&gt;
The math is the same, but the step values are different. That's how I look at it. &lt;/p&gt;
&lt;h2&gt;
  
  
  Free-Up Space
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;my_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;user_space&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;

    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cleaning_crew&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;user_space&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;cleaning_crew&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;is_free&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here too, pointer arithmetic dominates. What we literally did was point at the user_space and subtract 1. user_space here is a pointer to the space right after metadata2, so by subtracting 1 (which steps back by exactly one 24-byte struct), we just ended up right back at the start of metadata2.&lt;br&gt;
We then changed is_free to true to represent that indeed, the memory is free.&lt;/p&gt;
&lt;h2&gt;
  
  
  Finally
&lt;/h2&gt;

&lt;p&gt;Never forget to take the memory address and anchor it to a variable, or else it will be lost (like Casper's love for women), leading to a memory leak.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;    &lt;span class="c1"&gt;//here, i got the free space to use later, after i am done using i need to destroy it&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;my_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;my_malloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// here after i am done using teh memory i destroy it&lt;/span&gt;
    &lt;span class="n"&gt;my_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As I keep exploring computers, I explore life as a whole. It has been a lovely journey and a learning experience. Soon I will be exploring more complex topics and ideas I have in mind. Thank you, and have a lovely life ahead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdbool.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/mman.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;memory_size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;is_free&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;my_malloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;request_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;global_metadata&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;my_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;user_space&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;



&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;raw_memory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PROT_READ&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;PROT_WRITE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MAP_PRIVATE&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MAP_ANONYMOUS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;metadata1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;raw_memory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;metadata1&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;memory_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;metadata1&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;is_free&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;metadata1&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;global_metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metadata1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;//here, i got the free space to use later after done using i need to destroy it&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;my_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;my_malloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// here after i am done using teh memory i destroy it&lt;/span&gt;
    &lt;span class="n"&gt;my_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;my_malloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;request_size&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;

    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;metadata2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;global_metadata&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;


    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metadata2&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt;  &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metadata2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;is_free&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;metadata2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;memory_size&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;request_size&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;user_space&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;metadata2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;metadata3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)((&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;user_space&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;request_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;old_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metadata2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;memory_size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="n"&gt;metadata2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;is_free&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;metadata2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;memory_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request_size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;metadata3&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metadata2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;metadata2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metadata3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="n"&gt;metadata3&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;is_free&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;metadata3&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;memory_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;old_size&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;request_size&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;metadata3&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;user_space&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;metadata2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metadata2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;my_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;user_space&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;

    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cleaning_crew&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;user_space&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;cleaning_crew&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;is_free&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>c</category>
      <category>beginners</category>
      <category>memoryallocation</category>
      <category>programming</category>
    </item>
    <item>
      <title>Page-Based-Solution (Free-List Allocator)</title>
      <dc:creator>Gazel-create</dc:creator>
      <pubDate>Thu, 24 Sep 2026 07:42:29 +0000</pubDate>
      <link>https://dev.to/gazel-create/paging-solution-free-list-allocator-lfn</link>
      <guid>https://dev.to/gazel-create/paging-solution-free-list-allocator-lfn</guid>
      <description>&lt;p&gt;This is Part 2 of how memory is allocated by the OS. In the first part, I talked about the need for virtual pages and why I called it the "Page-Based Solution." Here, we will talk about how that approach creates its own set of new problems, and how the solutions keep popping up like the heads of a Hydra.&lt;/p&gt;

&lt;h2&gt;
  
  
  Aligning Memory
&lt;/h2&gt;

&lt;p&gt;Let’s talk about memory alignment. On a modern 64-bit architecture, the CPU reads data from RAM in 8-byte chunks (called "words"). If our memory isn't aligned, say, a 4-byte variable sits right across the boundary of two 8-byte chunks, the CPU has to read from memory twice just to stitch that single variable together. That makes it slow. But if we request a page from the OS, we are already getting a proper chunk of memory that is perfectly aligned to a 4096-byte boundary right out of the gate, making it faster and smoother. Sometimes, if we only need a tiny variable like a char, the system adds "filler" bytes (padding) to keep the next variable perfectly aligned to those 8-byte boundaries. You see? Keeping things aligned makes the CPU much more efficient.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In-band metadata in the heap.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Is it efficient for 32 bytes?"&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;You are 100% correct. It is horribly inefficient for tiny allocations.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If a user asks for 4 bytes, and your control panel (metadata struct) is 24 bytes, your overhead is 600%. You are wasting more space managing the memory than actually using it! In the real world, the Linux kernel solves this using "Slab Allocators." For tiny requests, the OS creates a massive grid of exactly 32-byte slots and uses just one control panel to manage hundreds of them.&lt;/p&gt;

&lt;p&gt;This is why I am going to show three main ways of allocating memory: Slab Allocator, Buddy Allocator, and Free-List Allocator.&lt;/p&gt;

&lt;p&gt;I wondered which one is the best, but apparently, each is situational. Right now, I don't fully know what that means, but let's see if by the end of this article, I will be able to pick the appropriate allocator style for different projects.&lt;/p&gt;

&lt;p&gt;Firstly, here is a skeleton of a manual memory allocation. I created two structs, each in charge of tracking free memory and used memory in a Linked List setting so it's easy to keep track of them. A good amount of pointer arithmetic was used, lool. I am not gonna explain the whole code just yet. The main idea of this article is to discuss different ways that memory allocation is possible.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdbool.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/mman.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt;  &lt;span class="n"&gt;node_data&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;memory_size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;is_free&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node_data&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;raw_memory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PROT_READ&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;PROT_WRITE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MAP_PRIVATE&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MAP_ANONYMOUS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node_data&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node_data&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;raw_memory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;is_free&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;memory_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node_data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%zu&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;memory_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;//Now for my 2nd struct to keep track of free space&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node_data&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;metadata2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node_data&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)((&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;is_free&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metadata2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;memory_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//gave 32 bytes to use&lt;/span&gt;

    &lt;span class="n"&gt;metadata2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;is_free&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;metadata2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;metadata2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;memory_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;memory_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node_data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The free size now is %zu&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;metadata2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;memory_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 


&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Slab Allocator:&lt;/strong&gt;&lt;br&gt;
This is considered to be the fastest because it keeps assigning the exact same block size of memory for every object. It is highly optimized, and due to the perks of same-sized blocks, it is usually used by the OS for repetitive things like Process tables and network socket buffers, which are always of fixed sizes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Buddy Allocator:&lt;/strong&gt;&lt;br&gt;
It uses powers of 2 to merge free memory spaces (like 2, 4, 8, 16... up to huge blocks). It prevents external fragmentation, and Linux uses it heavily. But it can have a lot of internal fragmentation. Since it relies on powers of 2, if you want 17 bytes, you get assigned 32 bytes. That's 15 bytes of wasted space sitting unused inside your block!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Free-List Allocator:&lt;/strong&gt;&lt;br&gt;
Here, there is a metadata linked list that keeps track of all the free space scattered across the page. It might be a bit slow because the allocator has to search through the list to find a block big enough for your request. Over time, it can suffer from fragmentation as chunks are split and freed in random orders, leaving tiny holes everywhere. But it is very flexible for general-purpose programming. However, like we saw above, if the linked list metadata is 24 bytes and we request 4 bytes... we used 24 bytes to keep track of 4 bytes. I don't think we can call that efficient for tiny allocations.&lt;/p&gt;
&lt;h2&gt;
  
  
  Code for Free-List Allocation
&lt;/h2&gt;

&lt;p&gt;Here is the code for a custom Free-List Allocator. The real magic happens right here through pointer arithmetic and linked-list traversal. This series isn't about doing a line-by-line code explanation, so I will keep it brief.&lt;/p&gt;

&lt;p&gt;You just have to remember the core mechanics: we need a "walker" pointer to traverse the linked list. A while loop is perfect for this, allowing us to conditionally step from one pointer to the next until we find a free block big enough for our request. Always maintain a global variable to keep track of the start of your list, and rely on pointer arithmetic to calculate your remaining free space.&lt;/p&gt;

&lt;p&gt;NGL, this was amazing to learn. Building a linked list that actively tracks state changes and dynamically slices up free memory on the fly is incredibly satisfying.&lt;/p&gt;

&lt;p&gt;It has been a pleasure writing and learning this alongside you. Have an awesome day, and stay linked with curiosity.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdbool.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/mman.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt;  &lt;span class="n"&gt;node_data&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;memory_size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;is_free&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node_data&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node_data&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;global_start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;my_malloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;request_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;raw_memory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PROT_READ&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;PROT_WRITE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MAP_PRIVATE&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MAP_ANONYMOUS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node_data&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node_data&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;raw_memory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;is_free&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;memory_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node_data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;global_start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;my_malloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;my_malloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;request_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node_data&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;metadata2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;global_start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metadata2&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metadata2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;is_free&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;metadata2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;memory_size&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;request_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

            &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;user_memory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;metadata2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node_data&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;metadata3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node_data&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)((&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;user_memory&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;request_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;old_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metadata2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;memory_size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="n"&gt;metadata2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;memory_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request_size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;metadata2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;is_free&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="n"&gt;metadata3&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metadata2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;metadata2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metadata3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="n"&gt;metadata3&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;is_free&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;metadata3&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;memory_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;old_size&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;request_size&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node_data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;user_memory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;metadata2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metadata2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>architecture</category>
      <category>computerscience</category>
      <category>performance</category>
    </item>
    <item>
      <title>Need Space? Hold My Page: The OS-to-Program Memory Boundary</title>
      <dc:creator>Gazel-create</dc:creator>
      <pubDate>Thu, 17 Sep 2026 07:08:49 +0000</pubDate>
      <link>https://dev.to/gazel-create/need-space-hold-my-page-the-os-to-program-memory-boundary-5237</link>
      <guid>https://dev.to/gazel-create/need-space-hold-my-page-the-os-to-program-memory-boundary-5237</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Before learning anything else, I believe we have to understand memory management. As I kept allocating dynamic memory in my programs, I started to think about what that actually means. I know it's virtual and it's available, but who gives it? Who is in charge? How does it happen?&lt;/p&gt;

&lt;p&gt;I am writing this article to answer those exact questions. This is a two-part series. I will start with what memory actually looks like and how the OS does its magic, and later move on to building a small memory allocator. I am going to start with sbrk() and move to mmap(), as it is the new standard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ask Heap for memory?
&lt;/h2&gt;

&lt;p&gt;In a Linux environment, a program's virtual memory heap has a defined upper boundary known as the "program break." Everything below this line—sitting just above the Data and BSS segments, is accessible heap memory. Everything immediately above this line is unmapped, and trying to access it will cause a crash (segmentation fault).&lt;/p&gt;

&lt;p&gt;Traditionally, we use the sbrk() system call to drag this program break up or down. If you ask sbrk() to expand the heap by 40 bytes, it pushes the boundary up and returns a void * pointer to the start of that new space.&lt;/p&gt;

&lt;p&gt;However, on modern architectures like RISC-V and ARM64, relying on sbrk() and brk() is deprecated. Modern custom allocators instead rely on mmap() (Memory Mapper) to request memory directly from the OS in chunks called "pages." A page is simply a fixed-size contiguous block of virtual memory (typically 4KB) that the operating system hands over to the program to manage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Need space? OS: "Hold my page"
&lt;/h2&gt;

&lt;p&gt;The memory we use is not a real, contiguous block of physical RAM. It is just an illusion we use to make programs work. In reality, physical memory is broken up into blocks called "frames," and the hardware stores our data wherever it finds free space, rarely in a straight line. This chaos is managed through a partnership between the OS and the CPU's Memory Management Unit (MMU).&lt;/p&gt;

&lt;p&gt;When a program asks the OS for memory, the OS provides a "page" for that process to work, play, or exist in. A page is simply the smallest chunk of memory that the OS will hand out to a program. Each virtual page is then linked to a raw physical memory frame, mapped together by a lookup table managed by the MMU. This is exactly how the illusion of continuous virtual memory is created.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Security:&lt;/strong&gt; Because each process is assigned its own page, its own playground, or dare I say, kingdom. They cannot cross over into another program's memory area. If a program tries to invade without permission, it is essentially declaring war, and the OS will instantly strike it down (Segmentation Fault).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Efficiency:&lt;/strong&gt; If the system is running low on physical RAM, the OS can look for pages belonging to different processes that aren't actively being used. It can simply copy or move those pages to the hard drive (swapping) and bring them back later if needed. The MMU keeps track of this as well, seamlessly mapping the memory addresses behind the scenes.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why Shifting the Program Break (sbrk) is Dead
&lt;/h1&gt;

&lt;p&gt;Modern architectures don't use sbrk() anymore; it has been deprecated. Moving a single program break line had a few major problems.&lt;/p&gt;

&lt;p&gt;Waste of memory: As we keep moving the break line up to add more chunks of memory for the program, we run into a trap. Suppose chunks A, B, and C are allocated in that order. The program finishes with chunk B and wants to free it. It tells the allocator B is free, but the OS cannot use that space again. Why? Because we cannot move the program break back down to the start of B without losing chunk C, which is sitting right on top of it. Layout and chronology dictate everything. We might say it is just 4 bytes trapped in the middle, but do it enough times, and it will eat a huge chunk of RAM through a compounding effect (this is known as fragmentation).&lt;/p&gt;

&lt;p&gt;Multi-threading: Because sbrk() plays with a single, global program break for the whole process, what happens if two threads call malloc() at the exact same time? They both try to move the same boundary line simultaneously. This causes a race condition leading to memory corruption and unpredictable outcomes.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Page-Based Solution
&lt;/h3&gt;

&lt;p&gt;With the help of tools like mmap(), we can request discrete, independent pages from the OS instead of moving a single global line. If we allocate independent pages for different data, we can give a specific page back to the OS the moment we are done with it, without affecting the others. This is much more efficient, and modern allocators can even assign entirely different pages to different threads, completely removing the race condition.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/mman.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Asking the OS for 4096 bytes of space (a typical page size)&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;raw_memory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PROT_READ&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;PROT_WRITE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MAP_PRIVATE&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MAP_ANONYMOUS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw_memory&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;MAP_FAILED&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Allocation failed!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Successfully allocated a page at: %p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;raw_memory&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Always return the page to the OS when done&lt;/span&gt;
    &lt;span class="n"&gt;munmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw_memory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why did I say "Page-Based" Solution? (Conclusion)
&lt;/h2&gt;

&lt;p&gt;Understanding virtual memory pages and physical memory frames paints a much clearer picture of what is happening under the hood when dealing with dynamic memory allocation. The OS has successfully handed us a 4KB block of space using mmap().&lt;br&gt;
But this creates a new problem: what if our program only needs to store an 8-byte integer? If we give it the entire 4KB page, we waste a massive amount of space.&lt;br&gt;
In Part 2, I will solve this by building a custom memory allocator in C that takes this raw OS page and efficiently slices it up for the program to use. Thank you for reading, and have a profound day!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>c</category>
      <category>memory</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>Chip8 in C++</title>
      <dc:creator>Gazel-create</dc:creator>
      <pubDate>Mon, 07 Sep 2026 12:38:49 +0000</pubDate>
      <link>https://dev.to/gazel-create/chip8-in-c-49i6</link>
      <guid>https://dev.to/gazel-create/chip8-in-c-49i6</guid>
      <description>&lt;p&gt;The reason I started this project is to learn more about C++, as we all know the best way of learning a programming language is to do projects, DO PROJECTS!!&lt;/p&gt;

&lt;p&gt;I used Austin Morlan's website to learn how to build it, it's quite good (&lt;a href="https://austinmorlan.com/posts/chip8_emulator/" rel="noopener noreferrer"&gt;https://austinmorlan.com/posts/chip8_emulator/&lt;/a&gt;). I made some tweaks which I found to be better for me. I will not be posting the whole codebase here, it's too long. What I will be sharing are snippets of code, what I learned from it, and what I found amazing or funny (projects can have their own jokes).&lt;/p&gt;

&lt;h2&gt;
  
  
  What is an Emulator ?
&lt;/h2&gt;

&lt;p&gt;An emulator is just hardware or software that lets the host system replicate conditions like the CPU, memory systems, clock cycles, etc., of the guest system whose functions/behaviour they want to simulate. It helps to bridge the architectural gap by making sure that each instruction code can be executed. In the case of Chip8, we have to simulate the hardware restrictions of the 1970s: a 64x32 screen, a 16-key keypad, timers, and a buzz sound.&lt;/p&gt;

&lt;p&gt;If you google Chip8, you will see that it is not actually a real physical device. It is a virtual machine/interpreter where you can interpret games (that was the intended purpose), like Pong or Space Invaders. It was a virtual language created in 1977 AD for a computer called COSMAC VIP.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building in C++
&lt;/h2&gt;

&lt;p&gt;I wanted to get familiar with C++, that's why I am here. Building a Chip8 emulator in C++. Well, I learned you need headers, classes to define objects, the standard library, built-in objects like std::ifstream, std::streampos, and so on. I will explain some parts that left a mark in my memory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Header Files
&lt;/h3&gt;

&lt;p&gt;Well, before C++, I had only used a header file for an FPGA (Tang Nano 9K) project which I did. It made the LED blink in intervals. But now I understand more, such as how we create a blueprint of the class which we will be using to create objects in the future. Two modes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Public:&lt;/strong&gt;&lt;br&gt;
The attributes and methods of the said class can be accessed by other functions or parts of the program that are not in the same class. It can be accessed from inside and outside the class. Mostly used for accessibility and ease of use.&lt;br&gt;
&lt;strong&gt;Private:&lt;/strong&gt;&lt;br&gt;
The term is called Encapsulation, where the scope is just within the class. Nobody from outside the class can access and change data from the attributes and methods. Well, it is good if you don't want some other part of the program to change things by mistake.&lt;/p&gt;

&lt;p&gt;Here, in my header, I put the important attributes like memory, program counter, etc., in private so that only the objects of the Chip8 class can access it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Chip8&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;public:&lt;/span&gt;
        &lt;span class="n"&gt;Chip8&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;LoadROM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nl"&gt;private:&lt;/span&gt;
        &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;registers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;]{};&lt;/span&gt;
        &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;]{};&lt;/span&gt;
        &lt;span class="kt"&gt;uint16_t&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;{};&lt;/span&gt;
        &lt;span class="n"&gt;uint_16_t&lt;/span&gt; &lt;span class="n"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;{};&lt;/span&gt;
        &lt;span class="kt"&gt;uint16_t&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;]{};&lt;/span&gt;
        &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;{};&lt;/span&gt;
        &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;delayTimer&lt;/span&gt;&lt;span class="p"&gt;{};&lt;/span&gt;
        &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;keypad&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;]{};&lt;/span&gt;
        &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;]{};&lt;/span&gt;
        &lt;span class="kt"&gt;uint16_t&lt;/span&gt; &lt;span class="n"&gt;opcode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are wondering what is that block of code which is public? well it is a constructor. Lets talk about it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Constructors in C++
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;Chip8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Chip8&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="c1"&gt;//vs&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Chip8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;LoadROM&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="c1"&gt;//vs&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ifstream&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Constructors never have return types like void or int; their names must match the class, like in the above example Chip8::Chip8. Here, line 1 represents a default constructor which has no values inside the parentheses. In line 3, void Chip8::LoadROM(), we just created a method/function/action for the Chip8 class to perform when invoked. Line 5 is something special: std is a built-in prefix that tells the compiler to look for functions, objects, or variables inside the built-in library of C++. It is like a built-in tool that C++ provides. Like ifstream here, which is an object from std that reads data from files on the computer instead of the console.&lt;/p&gt;

&lt;p&gt;I also wanna talk about "::", the scope specifier (the beauty of C++ they say), which tells the compiler, in our example "std::ifstream", that ifstream belongs to the standard library. Everything is from this library; hence, no clashes in the future with names or data assignments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Member Initializer List
&lt;/h3&gt;

&lt;p&gt;Now look at this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;Chip8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Chip8&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;randGen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;chrono&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;system_clock&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;time_since_epoch&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;{.....&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do you see "::" then ":"? What is the difference? If one is a scope specifier, the other is a Member Initializer List. It helps the constructor to build space and get that particular variable ready to work, without wasting time by creating it again inside the constructor during the initialization process for the object. We can add more to the initialization list by just separating them with comma. You can look at the code below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;Chip8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Chip8&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
    &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;randGen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;chrono&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;system_clock&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;time_since_epoch&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
      &lt;span class="n"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x200&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;       
      &lt;span class="n"&gt;delayTimer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Infinite Wait
&lt;/h3&gt;

&lt;p&gt;I also learned the way to wait, when u want a key value pressed, but is not pressed then we just loop by decreasing the PC by 2 (2 because each instruction is 16 byte for Chip8), which gives the illusion of holding still, but its just same instruction on loop. I dont know about you guys, but to me when I undrstood, that i think my mind just unlocked a different way of looking at what wait is? what pause it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reading Instructions
&lt;/h3&gt;

&lt;p&gt;The code below is one of the instructions, which has its own function. There is alot to unpack.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Chip8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;OP_8xyE&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;//Set Vx = Vx SHL 1&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
&lt;span class="mi"&gt;3&lt;/span&gt;   &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;Vx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opcode&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x0F00u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8u&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;   &lt;span class="c1"&gt;// Save MSB in VF&lt;/span&gt;
&lt;span class="mi"&gt;6&lt;/span&gt;   &lt;span class="n"&gt;registers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0xF&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;registers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Vx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x80u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;7u&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;7&lt;/span&gt;
&lt;span class="mi"&gt;8&lt;/span&gt;   &lt;span class="n"&gt;registers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Vx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, I wrote a function of class Chip8 which returns nothing, hence void. The instruction here is 8xyE. I read that the naming convention for the Chip-8 opcode was restricted by memory space, hence you are going to find a few things out of order which will not make sense (Go take a look to see what I mean).&lt;/p&gt;

&lt;p&gt;Let's look at line 3. Here, the uint8_t datatype means unsigned integer of 8 bits. What's the difference between this and a normal unsigned integer? A standard int is usually 4 bytes (32 bits), while this is strictly 1 byte (8 bits). And no matter which machine architecture you are using, it will always be exactly 8 bits.&lt;/p&gt;

&lt;p&gt;(opcode &amp;amp; 0x0F00u) — is this line not something that you would expect to see on a hardcore programmer's screen in a movie or something? Here, a Bitwise AND is happening. In a sense, this operation will combine two streams of binary data and unify it by doing an AND switch. Like 101 AND 100 = 100. Just saying, if you study computers, you know the AND operation!&lt;/p&gt;

&lt;p&gt;So, how does the AND logic help us here? Think of F as a mask. In hexadecimal, F is 1111 in binary (all ones), and 0 is 0000 (all zeros). When we AND the opcode (8xyE) with the mask (0x0F00), the zeros wipe out the 8, the y, and the E. Only the digit that is placed at the same position as the F survives. So, 0x8xyE AND 0x0F00 leaves us with exactly 0x0x00. The u at the end is just saying the 0x0F00 is an unsigned integer.&lt;/p&gt;

&lt;p&gt;Next, &amp;gt;&amp;gt; is another bitwise operator which shifts the value 8 bits to the right. Because each hex character is 4 bits long, shifting right by 8 bits pushes the value over by exactly two hex spaces. It takes our 0x0x00 and slides it right to become 0x000x. We successfully extracted x!&lt;/p&gt;

&lt;p&gt;Wait, let's clear something up that confused me at first. In the opcode 8xyE, you might be wondering: "I only have 16 registers (0 to F), so how can I reference 'x' which doesn't even exist?"&lt;/p&gt;

&lt;p&gt;Here is the trick: 8xyE is just a template. The x and y are placeholders. In a real game, the emulator doesn't see 8xyE; it reads an actual hex number like 835E. The 8 and the E tell our emulator which operation to perform. The x becomes 3, and the y becomes 5. Since x is a single hex digit, it will always be a number from 0 to F (0 to 15 in decimal), which perfectly matches our 16 registers!&lt;/p&gt;

&lt;p&gt;So, back in line 3: uint8_t Vx = (opcode &amp;amp; 0x0F00u) &amp;gt;&amp;gt; 8u;&lt;br&gt;
This line doesn't give us the value of the register. It extracts that x (like the 3) to give us the box number (the index). It tells the program, "We need to look inside register 3." The actual value sitting inside that register was put there by some previous instruction earlier in the game.&lt;/p&gt;

&lt;p&gt;Now, to line 6. The Chip-8 has 16 registers (0-F), and here we are assigning a value to register F (registers[0xF]). I did a bitwise AND to the register value Vx (which we got from line 3) with 0x80u and shifted it right by 7 (&amp;gt;&amp;gt; 7u). But why??&lt;/p&gt;

&lt;p&gt;Let me explain. In line 8, we are going to shift the entire Vx register to the left by 1. But when you shift binary numbers left, the leftmost bit (the Most Significant Bit, or MSB) falls off the edge and gets lost. The Chip-8 instruction manual tells us we have to catch that falling bit and save it in the VF register (registers[0xF]) as a flag.&lt;/p&gt;

&lt;p&gt;Here is the magic: 0x80 in binary is 1000 0000. When we use the AND operator (&amp;amp;) against our register, it acts like a mask that zeros out all the bits except for that very first one on the far left. So, we are left with either 1000 0000 (if the bit was a 1) or 0000 0000 (if the bit was a 0).&lt;/p&gt;

&lt;p&gt;But we don't want to store 1000 0000; we just want a simple 1 or 0. That is where &amp;gt;&amp;gt; 7u comes in! Shifting it right by 7 spaces takes that bit from the far left and slides it all the way to the far right, turning 1000 0000 into 0000 0001. Boom, we just saved our MSB!&lt;/p&gt;

&lt;p&gt;Finally, we get to line 8:&lt;br&gt;
registers[Vx] &amp;lt;&amp;lt;= 1;&lt;/p&gt;

&lt;p&gt;Now that we saved our falling MSB in the flag register (0xF), we can safely do what this instruction was actually designed to do. We go into registers&lt;a href="https://dev.toour%20box"&gt;Vx&lt;/a&gt;, grab the data sitting inside, and use &amp;lt;&amp;lt;= 1 to shift all its bits to the left by 1. Fun fact: in binary, shifting left by 1 is the exact same thing as multiplying the number by 2!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;register[Vx] &amp;lt;&amp;lt; = 1&lt;br&gt;
//same as&lt;br&gt;
register[Vx] = register[Vx] * 2&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Function Pointer Tables
&lt;/h3&gt;

&lt;p&gt;I remember when I was a kid, I used to go to McDonald's with my dad and he would ask me, "Which number do you want?" I always said Number 3, as it was a McSpicy with fries and a drink. This reminds me of the exact same idea. Instead of saying "I want a McSpicy, fries, and a drink," you just say "3" and they know exactly what it is.&lt;/p&gt;

&lt;p&gt;Similarly, here, a function pointer table is just an array of pointers that point to functions.&lt;/p&gt;

&lt;p&gt;Conditional statements like switch and if are used to find which line of code to execute according to an event. But with an array of pointers, we just provide a number and point straight to a specific location. Done.&lt;/p&gt;

&lt;p&gt;This helps us reduce the code size and gives us O(1) time complexity. Because we don't need to search or compare, the computer just takes in the index, multiplies it by the pointer size, and jumps straight to the exact memory address! (Such a smart idea)&lt;/p&gt;
&lt;h3&gt;
  
  
  Score Board (Keep Count)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;CHip8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;OP_Fx33&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;uint8_Vx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opcode&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x0F00u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8u&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;registers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Vx&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="c1"&gt;//Ones&lt;/span&gt;
    &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;/=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;//Tens&lt;/span&gt;
    &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;/=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;//hundreds&lt;/span&gt;
    &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This instruction, Fx33, is used for something called Binary-Coded Decimal (BCD). Computers think in binary and hex, but what if a game like Pong needs to display a score of "156" on the screen to the human player? The game needs to draw the sprite for "1", then "5", then "6". It needs a way to break that single number apart into individual digits.&lt;/p&gt;

&lt;p&gt;The code above does this using a super clever math trick with the Modulo (%) and Division (/) operators, working backwards from right to left!&lt;/p&gt;

&lt;p&gt;Let's pretend our value is 156.&lt;br&gt;
First, we do 156 % 10. Modulo gives us the remainder of division, which is exactly 6. We store that 6 in memory as our "ones" place. Next, we do value /= 10. Because this is integer math, it doesn't give us decimals; it just chops the 6 right off the end, leaving us with 15.&lt;/p&gt;

&lt;p&gt;Then we just rinse and repeat!&lt;br&gt;
15 % 10 leaves us with 5 (our tens place). Chop it off (15 / 10) and we are left with 1.&lt;br&gt;
Finally, 1 % 10 leaves us with 1 (our hundreds place).&lt;/p&gt;

&lt;p&gt;We just successfully peeled apart the number digit by digit and stored them in memory so the screen can draw them later.&lt;/p&gt;
&lt;h3&gt;
  
  
  Saving Game
&lt;/h3&gt;

&lt;p&gt;The instruction Fx55 is used to save the game.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Chip8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;OP_Fx55&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;   &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;Vx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opcode&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x0F00u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8u&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;   &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;Vx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;6&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;7&lt;/span&gt;       &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;registers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="mi"&gt;8&lt;/span&gt;   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we did the usual: a bitwise AND (&amp;amp;), followed by bit shifting 8 bits to the right (&amp;gt;&amp;gt;), and assigned that 1 byte of data to our 8-bit unsigned integer variable named Vx.&lt;/p&gt;

&lt;p&gt;After that, we created a for loop where we initialized an unsigned integer uint8_t i = 0. I was wondering why it had to be uint8_t, but it makes sense because our registers use the same data type. We only need to count up to 15 anyway, so it's the most memory-efficient choice. We loop from 0 up to that specific "x" register index.&lt;/p&gt;

&lt;p&gt;Also, a thing to note: ++i is better than i++. When we do ++i (pre-increment), we don't have to create a temporary clone of i. With i++ (post-increment), C++ creates a copy of the variable after the first loop, does the arithmetic to add 1, and returns it. But ++i just adds 1 directly while the condition itself is being evaluated. It is preemptive and slightly faster.&lt;/p&gt;

&lt;p&gt;Then for line 7, where is this data actually going? The index variable here represents the CHIP-8's special I register (Index register). This register holds a memory address pointing to a specific location in the CHIP-8's main RAM. By doing memory[index + i], we make sure the memory steps forward one block at a time to handle each register's value.&lt;/p&gt;

&lt;p&gt;At first, I thought this meant we were saving the whole state of the game—all the indexes, the program counter, everything. But no! This isn't a "Save Game" feature like on a PlayStation. The emulator isn't saving to your hard drive. Games used this instruction to temporarily back up a few variables from the registers into the working RAM. So, that we can do some other task and later the game uses a different instruction (Fx65) to load them back out.&lt;/p&gt;

&lt;h3&gt;
  
  
  What kind of magic is this ?
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Chip8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Table0&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;table0&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;opcode&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x000Fu&lt;/span&gt;&lt;span class="p"&gt;]))();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When I first wrote this line, I looked at it and thought, what kind of magic is this? It looks like someone just smashed their keyboard. But if we break it down, it actually perfectly connects to our McDonald's Function Pointer Table from earlier!&lt;/p&gt;

&lt;p&gt;In the CHIP-8, there are a couple of different instructions that start with a 0 (like 00E0 to clear the screen, and 00EE to return from a subroutine). Because they share the same starting number, our emulator needs a secondary menu (table0) to tell them apart. To do that, it needs to look at the very last digit.&lt;/p&gt;

&lt;p&gt;First, we see our old friend the Bitwise AND: opcode &amp;amp; 0x000Fu. Because the F is at the very end of the mask this time, it wipes out the first three digits of the opcode and saves only the last one. If our opcode is 00EE, it leaves us with just the E.&lt;/p&gt;

&lt;p&gt;That E (which is 14 in decimal) is our menu number. We pass it into table0[...] like an array index, and it instantly finds the correct function pointer for us&lt;/p&gt;

&lt;p&gt;The Syntax, why is it like that? Cause life wants us to find beauty in the ugly.&lt;br&gt;
((&lt;em&gt;this).&lt;/em&gt;( ... ))();.&lt;br&gt;
This is just standard (but ugly) C++ syntax for calling a function pointer that belongs to a class.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;this is a pointer pointing to our current CHIP-8 object.&lt;/li&gt;
&lt;li&gt;.* is an operator that tells C++ to bind the function we just found in the table to our specific CHIP-8 machine.&lt;/li&gt;
&lt;li&gt;The () at the very end is the trigger, it tells the program, "Okay, execute the function now!"
So, in one single, crazy-looking line of code, we extract the menu number, look up the recipe, and cook the food. Magic!&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Beauty of instructions? Or the curse of instructions numbering convention?
&lt;/h3&gt;

&lt;p&gt;Ngl, when I first wrote this part, I was just shocked to see so much code and found it highly redundant.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="nf"&gt;void&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Chip8&lt;/span&gt;&lt;span class="o"&gt;::*&lt;/span&gt;&lt;span class="n"&gt;Chip8Func&lt;/span&gt;&lt;span class="p"&gt;)();&lt;/span&gt;

        &lt;span class="n"&gt;Chip8Func&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0xF&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="n"&gt;Chip8Func&lt;/span&gt; &lt;span class="n"&gt;table0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0xE&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="n"&gt;Chip8Func&lt;/span&gt; &lt;span class="n"&gt;table8&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0xE&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="n"&gt;Chip8Func&lt;/span&gt; &lt;span class="n"&gt;tableE&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0xE&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
            &lt;span class="n"&gt;Chip8Func&lt;/span&gt; &lt;span class="n"&gt;tableF&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0x65&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Table0&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Table8&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;TableE&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;TableF&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OP_NULL&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember this from above? "I read that the naming convention for the Chip-8 opcode was restricted by memory space, hence you are going to find a few things out of order which will not make sense (Go take a look to see what I mean)." Now you will get why!&lt;/p&gt;

&lt;p&gt;Why do we need so many tables? This is what I call the curse of the Chip-8 instruction numbering convention. The creators of Chip-8 back in 1977 didn't organize things perfectly. Some starting numbers have just one instruction. But numbers like 0, 8, E, and F have a whole bunch of different instructions packed inside them.&lt;/p&gt;

&lt;p&gt;Let's look at a few cool C++ tricks happening here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;typedef&lt;/strong&gt;: Remember that ugly function pointer syntax from the last section? Instead of writing void (Chip8::*PointerName)() over and over, typedef lets us create a custom nickname. We named it Chip8Func. Now, we can just use Chip8Func to create our arrays, which looks so much cleaner.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The + 1 in the Arrays&lt;/strong&gt;: Why table[0xF + 1]? Arrays in C++ start counting at 0. Since 0xF is 15, an array of size 15 would only go up to index 14. By adding + 1 (making the size 16), we guarantee we have enough room to safely use F as an index. Look at tableF[0x65 + 1]. The F instructions go all the way up to Fx65 (like the memory save instruction we just looked at). So, we literally have to build an array with 102 empty slots just to reach index 0x65!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;OP_NULL()&lt;/strong&gt;: Because we just created an array with 102 slots for tableF, but only a handful of them are actual CHIP-8 instructions, what happens if the emulator accidentally picks an empty slot? It crashes. OP_NULL() is our safety net. We fill all the empty menu slots with OP_NULL, which basically tells the emulator, "Sorry, that item is not on the menu," and prevents the whole program from blowing up.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Access modifiers
&lt;/h3&gt;

&lt;p&gt;While trying to compile the code, I got a lot of errors: syntax errors, non-existing arguments in the class blueprint, couldn't find the missing SDL2 library for displaying the sprites, and so on. But the main thing that haunted me was Access Modifiers.&lt;/p&gt;

&lt;p&gt;I am being honest right now, I just removed my private: tag so everything is public-scoped in my header file.&lt;/p&gt;

&lt;p&gt;Here is what went wrong. When main.cpp was trying to talk to my Chip-8 brain, it ran into this concept called Access Modifiers. In C++, anything listed under private: is strictly locked inside the class. That means the "outside world" (main.cpp) is completely forbidden from touching it.&lt;/p&gt;

&lt;p&gt;The compiler was yelling at me that video, keypad, and Cycle() were "private within this context." Our main.cpp file needs to read the keypad, draw the video array to the screen, and run the CPU cycle, but it was locked out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Hypothetical Fix:&lt;/strong&gt;&lt;br&gt;
Open chip8.h. Find &lt;code&gt;uint32_t video[64 * 32]{};, uint8_t keypad[16]{};,&lt;/code&gt; and &lt;code&gt;void Cycle();&lt;/code&gt;(which were originally sitting under the private: label). Cut and paste them higher up in the file so they sit directly under the public: label. Boom. Connection fixed. &lt;br&gt;
But I deleted my private: scope entirely. I am proud of my robust solution, haha!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Yes, I am making it formal by calling this title Conclusion. I did learn a good amount, and yes, I am a better C++ programmer than I was when I started it. Will I become an emulator-making machine? Nope, unless someone pays me a lot, or I wanna play some games that are specific to that architecture/machine. The main goal for me to start this journey of building Chip-8 was to learn through practice, I need to increase the volume of work.&lt;/p&gt;

&lt;p&gt;This is not a tutorial, or a documentation, it is just a letter. One twinkling stardust, which I wanna collect enough of to paint my own starry night sky. Thank you for reading this. And as always, &lt;em&gt;Amor Fati&lt;/em&gt; to you all.&lt;/p&gt;

&lt;p&gt;[Tetris Gameplay on my Chip8 Emulator]&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmzr02nkyd2kffumyj1a3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmzr02nkyd2kffumyj1a3.png" alt=" " width="800" height="456"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Yes, I am good at Tetris.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>emulator</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Journey towards Mastering (Computers)</title>
      <dc:creator>Gazel-create</dc:creator>
      <pubDate>Sun, 30 Aug 2026 12:31:30 +0000</pubDate>
      <link>https://dev.to/gazel-create/journey-towards-mastering-computers-329h</link>
      <guid>https://dev.to/gazel-create/journey-towards-mastering-computers-329h</guid>
      <description>&lt;p&gt;Being persistent is hard when you have responsibilities, when you need to work to earn money, when you don't have time to do what you want. This is what I was telling myself every day, when I missed a daily coding challenge, when I couldn't finish a project on time, when I lay in bed tired.&lt;/p&gt;

&lt;p&gt;Motivation is not necessary. Just do it. Love your fate. This post is my special way of showing myself how much I want this. I have been learning computer science and doing things that I keep forgetting due to a lack of reinforcement. Hence, I have made a 3-month plan to learn and relearn all the basics to make myself a better programmer. This is my progress for Day 1.&lt;/p&gt;

&lt;p&gt;Also, I will not post Day 1, 2, 3, etc. for 90 days straight. I will only post when I have time, or when I have learned something significant that makes me smile or let out a small giggle that makes me look like a psycho hehe.&lt;/p&gt;

&lt;h1&gt;
  
  
  Day 1 : Single Linked List
&lt;/h1&gt;

&lt;p&gt;I started the task having an idea of what a linked list was, but I had no idea about the different varieties of linked lists:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Singly Linked List&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Doubly Linked List&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Circular Linked List&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Double Circular Linked List&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I started Day 1 by writing a few lines of code to make a singly linked list. I will just paste the program code right now, and then I will write about what was interesting to me.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;



&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt; &lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;

        &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;new_node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;malloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="n"&gt;new_node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="n"&gt;new_node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_node&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    

        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;next_node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next_node&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First thing was, I have used C++ before. Then, while trying to understand objects, I read a line from Gemini that said objects are just a cooler version of structs. Well, custom data structures are kinda like objects, I guess, it's just that you cannot put functions inside of structs. Also, the idea of custom data types is fun, and I have come to appreciate memory management with the help of C.&lt;/p&gt;

&lt;p&gt;The code is simple. It creates a singly linked list, where we create nodes using the struct data type. It uses pointers to new heap addresses, which are the size of the struct that we created. Later, we will destroy the memory one after another using free().&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, in the code above, you can see we referenced a pointer of the data type node that we haven't even finished creating. Do you see it? It is called a self-referencing struct, and the magic happens due to pointers. Yup, pointers are the MVP; the magical, fantastic idea of pointers. The compiler just knows and says, "Here I am gonna allocate 8 bytes for a 64-bit system, 'cause it is a pointer'.&lt;/p&gt;

&lt;p&gt;The core idea of a linked list is to have a starting point to reference the first node, and then we can start going to the next struct one by one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Always remember to delete/free the memory after use. Here, I have assigned a new struct to hold the pointer value to the next struct.&lt;br&gt;
'Cause the heap still has the nodes, I just copied the location of head and backtracked it, Last In First Out (LIFO) style. Fun fact:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;
&lt;span class="c1"&gt;//same as&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are just accessing the member ptr of the struct after dereferencing to follow the pointer to its actual memory address.&lt;/p&gt;

&lt;p&gt;In the end, it is a good practice to reset the pointer so that it does not cause any errors like a dangling pointer. Even though we deleted the memory address that head was pointing to, head will still point to that deleted address unless we reset it.&lt;/p&gt;

&lt;p&gt;Finally, I wanna say it was fun writing this blog/article, I don't know. I will keep posting my progress as I continue to peer deep into the colourful and blinding grandness of programming. Thank you for reading this, have a wonderful day.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>c</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
