<?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: Richard</title>
    <description>The latest articles on DEV Community by Richard (@vanderoost).</description>
    <link>https://dev.to/vanderoost</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%2F4134053%2F5e09adce-7039-4d1b-b766-d6ef17275e88.jpg</url>
      <title>DEV Community: Richard</title>
      <link>https://dev.to/vanderoost</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vanderoost"/>
    <language>en</language>
    <item>
      <title>Generating random floats</title>
      <dc:creator>Richard</dc:creator>
      <pubDate>Fri, 09 Oct 2026 12:41:29 +0000</pubDate>
      <link>https://dev.to/vanderoost/generating-random-floats-1p1l</link>
      <guid>https://dev.to/vanderoost/generating-random-floats-1p1l</guid>
      <description>&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/qa83_KrkVIM" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;We've already hand-rolled our own RNG in a &lt;a href="https://vanderoost.com/articles/2026/09/25/stop-using-rand/" rel="noopener noreferrer"&gt;previous article&lt;/a&gt;, to improve on what the C standard library &lt;code&gt;rand()&lt;/code&gt; gives us.&lt;/p&gt;

&lt;p&gt;We also talked about &lt;a href="https://vanderoost.com/articles/2026/10/02/how-floats-work/" rel="noopener noreferrer"&gt;how floats work&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this article, I want to combine the two. I want to find out how we can generate random floating-point numbers between 0 and 1, and improve our rng.c library.&lt;/p&gt;

&lt;h2&gt;
  
  
  The naive way
&lt;/h2&gt;

&lt;p&gt;We already created an &lt;code&gt;rng_f()&lt;/code&gt; function when we set up the rng.c library. But it generates random floats by dividing a random int by the max:&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="kt"&gt;float&lt;/span&gt; &lt;span class="nf"&gt;rng_f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&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="n"&gt;pcg32_random_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pcg32_global&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;UINT32_MAX&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="n"&gt;f&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 approach has a small bug. We want to generate in the range of [0.0, 1.0) so we want to get arbitrarily close to 1.0, but never hit it.&lt;/p&gt;

&lt;p&gt;Because of rounding, there is actually a chance that we hit 1.0.&lt;/p&gt;

&lt;p&gt;About 1 in 33.5 million. Any random integer of 2^32 - 128 or above rounds up to 2^32 when it's converted to a float, and 2^32 / 2^32 is exactly 1.0. This seems insignificant, but we were already generating millions of random numbers. The chance of it happening is quite high in that situation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking at float bits
&lt;/h2&gt;

&lt;p&gt;Let's reflect back on how floats work in memory.&lt;/p&gt;

&lt;p&gt;The mantissa (23 bits) can get you from a base number all the way up to (but not including) double that base number.&lt;/p&gt;

&lt;p&gt;This means that the smallest "step" we can take from a certain float depends on the size or &lt;em&gt;exponent&lt;/em&gt; of the float. Floats close to zero have very tiny granular steps. Large floats have a larger step size:&lt;/p&gt;

&lt;p&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%2F6a7xadtli9dy8w4sb2tg.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%2F6a7xadtli9dy8w4sb2tg.png" alt="Variable float resolution" width="800" height="186"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, the number 1.0 has the exponent &lt;code&gt;01111111&lt;/code&gt; (127) with the mantissa set to all zeros:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;00111111 10000000 00000000 00000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The closest float before hitting 2.0 has the same exponent as 1.0, but with the mantissa fully maxed out (all 1s):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;00111111 11111111 11111111 11111111
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So when we randomise the mantissa bits, we can get a random float. As long as we keep the exponent bits constant, we know we have a consistent step size.&lt;/p&gt;

&lt;h2&gt;
  
  
  Randomising the 23 mantissa bits
&lt;/h2&gt;

&lt;p&gt;In the &lt;a href="https://vanderoost.com/articles/2026/10/02/how-floats-work/" rel="noopener noreferrer"&gt;article on how floats work&lt;/a&gt;, we explored what the bits of a float mean, and how we can flip them.&lt;/p&gt;

&lt;p&gt;If we have an RNG that gives us some random bits, we can use them to randomise our float bits.&lt;/p&gt;

&lt;p&gt;So if we want to randomise the 23 mantissa bits of the float, this is how we can do that:&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;typedef&lt;/span&gt; &lt;span class="k"&gt;union&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;f&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;u&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;Bits&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;Bits&lt;/span&gt; &lt;span class="n"&gt;bits&lt;/span&gt; &lt;span class="o"&gt;=&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="n"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;|=&lt;/span&gt; &lt;span class="n"&gt;rng_u&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="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;23&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 use the union trick to be able to access float memory as if it's an integer. This allows for bitwise operations. Then we take a random 32-bit integer from &lt;code&gt;rng_u()&lt;/code&gt;, and shift it 9 places to the right (32 - 23). This shift zeroes out the top 9 bits, so the OR only sets mantissa bits and leaves the sign and exponent bits of the float alone.&lt;/p&gt;

&lt;p&gt;If you start at the number 0, and you randomise the mantissa bits, you get a random range between 0.0 and about 1.18 × 10⁻³⁸. That's 37 zeros after the decimal point! These tiny values are called subnormal numbers.&lt;/p&gt;

&lt;p&gt;Not very practical for our target range of [0, 1) I reckon. This is because of that variable resolution that we get in floats.&lt;/p&gt;

&lt;p&gt;If we start with the number 0.5 though, and randomise the mantissa, we achieve a range of [0.5, 1.0). That's starting to look more like it.&lt;/p&gt;

&lt;p&gt;But starting at 0.5 gives us a total "range length" of 0.5 (1 - 0.5 = 0.5). The target range of 0 to 1 has a length of 1. So what if we start from 1?&lt;/p&gt;

&lt;p&gt;Then the range becomes [1, 2). So we get the desired length of the range; it's only shifted up by 1. If we then subtract 1, we land exactly in range [0, 1). This is what that looks like in C:&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;Bits&lt;/span&gt; &lt;span class="n"&gt;bits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{.&lt;/span&gt;&lt;span class="n"&gt;f&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="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="n"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;|=&lt;/span&gt; &lt;span class="n"&gt;rng_u&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="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f&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="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We start from a base of 1.0f. Then randomise the lowest 23 bits (mantissa bits) to vary our range between 1 and 2 (not including 2). Finally we subtract 1. That subtraction is exact: no rounding happens, so every value lands precisely in [0, 1).&lt;/p&gt;

&lt;p&gt;Now we have a very efficient way to turn a random 32-bit int into a random 32-bit float between 0 and 1.&lt;/p&gt;

&lt;p&gt;But we can do better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Doubling the resolution
&lt;/h2&gt;

&lt;p&gt;Let's take a closer look at the structure of a float.&lt;/p&gt;

&lt;p&gt;We want equally spaced out floats in the range of 0 to 1. This is not trivial, because if you consider ALL floats between 0 and 1, you get a large variety of step sizes, as we saw in the drawing above.&lt;/p&gt;

&lt;p&gt;The steps close to 0.0 are a lot more fine-grained than the steps close to 1. So which step size do we choose? We choose the smallest one that works everywhere between 0 and 1. That means we should choose the step size of the range [0.5, 1).&lt;/p&gt;

&lt;p&gt;Because if you go down the exponent, closer to zero, you keep dividing by 2. So the step size between [0.25, 0.5) is half the step size of [0.5, 1). This is fine; we just have to pick every other step between [0.25, 0.5) to stick to a constant step size. Same for the range below that, [0.125, 0.25), we pick every 4th step, and so on.&lt;/p&gt;

&lt;p&gt;So what does this mean? The step size we can take is the smallest increment within the [0.5, 1) range. We can calculate that by manipulating bits:&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;Bits&lt;/span&gt; &lt;span class="n"&gt;bits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{.&lt;/span&gt;&lt;span class="n"&gt;f&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="mi"&gt;5&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="n"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;u&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;float&lt;/span&gt; &lt;span class="n"&gt;step_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f&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="mi"&gt;5&lt;/span&gt;&lt;span class="n"&gt;f&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;"step size: %.10f (%a)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;step_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;step_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives us an ideal step size of around &lt;code&gt;0.0000000596&lt;/code&gt;, or more exactly &lt;code&gt;0x1p-24&lt;/code&gt;, so &lt;code&gt;1 * 2 ^ -24&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What is the step size we're currently using when we generate floats using the random mantissa and subtract 1 method?&lt;/p&gt;

&lt;p&gt;That step size is twice as big, because we're generating a float between [1, 2), which is the next level up from [0.5, 1).&lt;/p&gt;

&lt;p&gt;So although that method works, we're throwing away half of our possible floating-point numbers between 0 and 1 that we could have had.&lt;/p&gt;

&lt;p&gt;Instead of 23 bits of randomness, we could add a 24th bit and double our resolution.&lt;/p&gt;

&lt;p&gt;How can we do this? We could go back to starting from 0.5, randomising the mantissa to get the range [0.5, 1). And then with 50% chance, subtract 0.5f from that. That could definitely work, but there is a much simpler and more boring solution that we'll explore next.&lt;/p&gt;

&lt;h2&gt;
  
  
  Back to basics
&lt;/h2&gt;

&lt;p&gt;We looked at the ideal step size for the range of random numbers to pick from between 0 and 1. This turned out to be the number 2^-24 or 1 / 2^24.&lt;/p&gt;

&lt;p&gt;We've also seen how we can generate 32 random bits, and take 23 of them to randomise bits in a float.&lt;/p&gt;

&lt;p&gt;What if we took an extra random bit, 24 in total? This gives us an integer range of [0, 2^24). The 2^24 is not included, because if you have 24 bits maxed out (all 1s), it equals 2^24 - 1.&lt;/p&gt;

&lt;p&gt;We can recognise that 2^24 / 2^24 = 1, obviously. And since we don't quite reach 2^24, we get (2^24 - 1) / 2^24 which is almost 1 (one step below 1). You might also realise that if we divide the integer value of our 24 random bits by 2^24, we end up in our desired range of [0, 1).&lt;/p&gt;

&lt;p&gt;Dividing by 2^24 is the same as multiplying by 2^-24 (our step size). Your compiler turns either one into the same multiplication, but writing it as a multiplication makes the step size explicit. So now it all comes together. Since the step size of our integer range is 1, if we multiply by 2^-24, this is the new step size.&lt;/p&gt;

&lt;p&gt;So the improved method for converting a 32-bit integer to a 32-bit float in range [0, 1) becomes:&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;// Generate 24 random bits&lt;/span&gt;
&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;bits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rng_u&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="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Multiply by the smallest step size to generate a float between 0-1&lt;/span&gt;
&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bits&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mh"&gt;0x1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's all. And it fixes the bug from earlier: every 24-bit integer fits in a float exactly, so the conversion never rounds, and the result can never reach 1.0.&lt;/p&gt;

&lt;p&gt;This magical-looking &lt;code&gt;0x1.0p-24f&lt;/code&gt; is hexadecimal float notation (added in C99). It allows us to specify an exact float value.&lt;/p&gt;

&lt;p&gt;The start &lt;code&gt;0x&lt;/code&gt; means we're about to write a hexadecimal number. The &lt;code&gt;1.0&lt;/code&gt; is the mantissa in hex format (but in decimal format 1.0 is the same). And finally &lt;code&gt;p-24&lt;/code&gt; means "times 2 to the power of -24" (p instead of e, because e is a hexadecimal digit). The exponent is written in decimal, and it's always a power of 2. It ends with an &lt;code&gt;f&lt;/code&gt; to make sure it's a 32-bit float and not a 64-bit double.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tucking it into the library
&lt;/h2&gt;

&lt;p&gt;With this method of converting 32 random bits to a clean float in [0, 1), let's integrate it into our rng.c library.&lt;/p&gt;

&lt;p&gt;This is what our random integer function looks like:&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;static&lt;/span&gt; &lt;span class="kr"&gt;inline&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="nf"&gt;rng_u&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&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="n"&gt;pcg32_random_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pcg32_global&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;Let's create an &lt;code&gt;rng_f()&lt;/code&gt; function in the same vein:&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;static&lt;/span&gt; &lt;span class="kr"&gt;inline&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nf"&gt;rng_f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pcg32_random_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pcg32_global&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;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mh"&gt;0x1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="n"&gt;f&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;Instead of calling &lt;code&gt;rng_u()&lt;/code&gt; we call &lt;code&gt;pcg32_random_r&lt;/code&gt; directly. The compiler would inline &lt;code&gt;rng_u()&lt;/code&gt; anyway, but this keeps the two functions symmetrical.&lt;/p&gt;

&lt;p&gt;And we shift 8 bits. That's like saying "discard the 8 lowest bits", so we're left with 24 bits.&lt;/p&gt;

&lt;p&gt;And that's it! You can check out the code in the &lt;a href="https://github.com/vanderoost/rng.c" rel="noopener noreferrer"&gt;rng.c repo&lt;/a&gt;. If it looks a bit different by the time you read this, that might be because I've improved some things :)&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://vanderoost.com/articles/2026/10/09/better-random-floats/" rel="noopener noreferrer"&gt;vanderoost.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://vanderoost.com/articles/2026/09/25/stop-using-rand/" rel="noopener noreferrer"&gt;Stop using rand()&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vanderoost.com/articles/2026/10/02/how-floats-work/" rel="noopener noreferrer"&gt;Hacking floats to learn how they work&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/vanderoost/rng.c" rel="noopener noreferrer"&gt;rng.c on Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>algorithms</category>
      <category>programming</category>
      <category>softwaredevelopment</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Hacking floats to learn how they work</title>
      <dc:creator>Richard</dc:creator>
      <pubDate>Fri, 02 Oct 2026 12:00:20 +0000</pubDate>
      <link>https://dev.to/vanderoost/how-floats-work-2853</link>
      <guid>https://dev.to/vanderoost/how-floats-work-2853</guid>
      <description>&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/ksumuyRAk-U" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In this article I want to explore floating-point numbers (floats). Floats are a bit more complicated than integers. It's quite easy to convert a bunch of bits to an (unsigned) integer, but for floats this is not trivial.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing C
&lt;/h2&gt;

&lt;p&gt;I don't always write C, but when I do, I tend to find myself learning &lt;em&gt;how things work&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In other languages, it's a lot more common to just import modules for everything. In C, it's more conventional to "write it yourself". Write your own string library, write your own data structures, etc.&lt;/p&gt;

&lt;p&gt;It might not be the fastest way to get things done, but if your goal is to &lt;em&gt;learn&lt;/em&gt;, coding in C is very effective.&lt;/p&gt;

&lt;p&gt;So what I want to do is try to reverse engineer floats in C: Create some floats, look at what their bits in memory look like, and figure out what does what.&lt;/p&gt;

&lt;h2&gt;
  
  
  How many bits?
&lt;/h2&gt;

&lt;p&gt;If we want to know what the bits of a float look like in memory, we first need to know some very basic information: how many bits make a float?&lt;/p&gt;

&lt;p&gt;The way to get the number of &lt;em&gt;bytes&lt;/em&gt; is by using &lt;code&gt;sizeof&lt;/code&gt;:&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="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;float_bytes&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="kt"&gt;float&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;"a float has %zu bytes&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;float_bytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prints &lt;code&gt;a float has 4 bytes&lt;/code&gt; on my system (and it will on most systems). There are 8 bits per byte, so a float has 4 * 8 = 32 bits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accessing bits of integers
&lt;/h2&gt;

&lt;p&gt;In C you can do bitwise operations to access individual bits. But this only works with integers.&lt;/p&gt;

&lt;p&gt;This is how you can access the first (lowest) bit of an unsigned integer called &lt;code&gt;u&lt;/code&gt;:&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="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;123&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;bit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;1u&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;"bit: %u&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;bit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm using the type &lt;code&gt;uint32_t&lt;/code&gt; here. This is an unsigned 32-bit integer. Unsigned integers are the easiest to convert from binary to decimal as we don't have to worry about the sign. And it's 32 bits, the same size as a float. This will become relevant later.&lt;/p&gt;

&lt;p&gt;We're using the bitwise operator &lt;code&gt;&amp;amp;&lt;/code&gt; (AND), which compares two integers bit by bit, and returns a third integer bit by bit (or bitwise).&lt;/p&gt;

&lt;p&gt;So if you do &lt;code&gt;a &amp;amp; b&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; is the number 1, which corresponds to &lt;code&gt;00000000 00000000 00000000 00000001&lt;/code&gt; in binary, you're basically only focusing in on the first (smallest, rightmost) bit, masking out the rest. If the smallest bit of &lt;code&gt;a&lt;/code&gt; is a 0, the result is 0; if it's a 1, the result is 1.&lt;/p&gt;

&lt;p&gt;Ok, so how do you access the other bits?&lt;/p&gt;

&lt;p&gt;If you do a bitwise AND with the second bit:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;00000000 00000000 00000000 00000010&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You will focus on the second bit, but you will get back either a 0, or the value of that bit (2).&lt;/p&gt;

&lt;p&gt;This second bit corresponds to 2 in decimal, so you can do an &lt;code&gt;&amp;amp; 2&lt;/code&gt; on it:&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="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&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;bit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;2&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;"bit: %u&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;bit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But this returns a 2.&lt;/p&gt;

&lt;p&gt;If we just want to get back a 0 or a 1, we can instead &lt;em&gt;shift&lt;/em&gt; the number to move the bit we want to see to the lowest place, and then AND it with a 1.&lt;/p&gt;

&lt;p&gt;So if we want to get the second bit, we do this:&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="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&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;bit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;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;&amp;amp;&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;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"bit: %u&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;bit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This now returns a 1 instead of a 2.&lt;/p&gt;

&lt;p&gt;We can generalize this and provide a bit index &lt;code&gt;bit_ix&lt;/code&gt; that can range from 0 to 31 for 32-bit numbers.&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="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&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;bit_ix&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;uint32_t&lt;/span&gt; &lt;span class="n"&gt;bit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bit_ix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&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;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"bit: %u&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;bit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm using a &lt;code&gt;size_t&lt;/code&gt; type here for the bit index. This is just something I usually do for sizes, indices, etc.&lt;/p&gt;

&lt;p&gt;Now we have a good way to access every individual bit of an int.&lt;/p&gt;

&lt;p&gt;Let's print all of them to the screen:&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="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&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;size_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="mi"&gt;32&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;bit_ix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;31&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="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;bit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bit_ix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&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;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%u"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bit&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;"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;00000000000000000000000000000011
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prints out a bunch of bits: that's what the memory looks like for &lt;code&gt;3&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We have to sort of invert the &lt;code&gt;bit_ix&lt;/code&gt;. We start at 31 and walk back to 0, so that we print the highest bits first and go down to the lowest bits. Just like how we treat decimal numbers as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accessing float memory like it's an int
&lt;/h2&gt;

&lt;p&gt;These bitwise operations won't work on floats:&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="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;f&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;bit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;1u&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;"bit: %u&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;bit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;error: invalid operands to binary expression ('float' and 'unsigned int')
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we have to figure out a way to convert the float into an int.&lt;/p&gt;

&lt;p&gt;If we do this:&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="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;f&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="n"&gt;f&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;u&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code compiles, but the float is converted to a &lt;code&gt;uint32_t&lt;/code&gt;, which means the bits in memory are all changed. A &lt;code&gt;1.0f&lt;/code&gt; float becomes a &lt;code&gt;1&lt;/code&gt; int because that makes the most sense.&lt;/p&gt;

&lt;p&gt;But what we want is to look at the bits of a float as if the memory belongs to an int, such that we can access the bits.&lt;/p&gt;

&lt;p&gt;There are two approaches to do this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pointers&lt;/li&gt;
&lt;li&gt;Unions&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's try both.&lt;/p&gt;

&lt;h3&gt;
  
  
  The pointer method
&lt;/h3&gt;

&lt;p&gt;If we convert a float to an int, we're interpreting the float as an int, and we set the memory that belongs to the int to whatever the float represents "numerically".&lt;/p&gt;

&lt;p&gt;Instead, what we want is to create a float, and access its memory as if those 32 bits belong to a &lt;code&gt;uint32_t&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In order to do that, we first create a float:&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="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;f&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="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we create a pointer to that float's address:&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="kt"&gt;float&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we can create a &lt;code&gt;uint32_t&lt;/code&gt; pointer, which also just points to a place in memory. We can cast the float pointer to be a &lt;code&gt;uint32_t&lt;/code&gt; pointer and point to the same thing:&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="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then we can create a &lt;code&gt;uint32_t&lt;/code&gt; and set it equal to whatever the &lt;code&gt;uint32_t&lt;/code&gt; pointer is pointing to (the float memory).&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="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;up&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have created a &lt;code&gt;uint32_t&lt;/code&gt; from a float, but without converting the value. We only cast the pointer types, which doesn't mess with the memory.&lt;/p&gt;

&lt;p&gt;So all together, we can now print out the individual bits of a float:&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="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;f&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="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;fp&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;u&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;up&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;size_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="mi"&gt;32&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="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;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;8&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="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;" "&lt;/span&gt;&lt;span class="p"&gt;);&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;bit_ix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;31&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="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;bit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bit_ix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&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;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%u"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bit&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;"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, I'm printing out a space every 8th bit, to group the bits as bytes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;00111111 10000000 00000000 00000000
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's what the float &lt;code&gt;1.0f&lt;/code&gt; looks like in memory!&lt;/p&gt;

&lt;p&gt;There is a catch though. Technically, this breaks C's &lt;em&gt;strict aliasing&lt;/em&gt; rule: you're not supposed to read an object through a pointer of a different type. We're being sneaky hackers here. Officially, it's undefined behavior, and with optimizations turned on, the compiler might change the behaviour. In practice it usually works, but that's one more reason to prefer the next method.&lt;/p&gt;

&lt;h3&gt;
  
  
  The union method
&lt;/h3&gt;

&lt;p&gt;This is, in my opinion, the easier method to understand, provided you know what a union is.&lt;/p&gt;

&lt;p&gt;The syntax for a union looks just like the syntax for a struct in C:&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;typedef&lt;/span&gt; &lt;span class="k"&gt;union&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;f&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;u&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;Bits&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The difference between a struct and a union is that a struct places all its members sequentially in memory:&lt;/p&gt;

&lt;p&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%2F027pl2fe7zsif0ecevfn.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%2F027pl2fe7zsif0ecevfn.png" alt="Struct" width="798" height="198"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unions on the other hand place the members "on top of" each other, using the same memory:&lt;/p&gt;

&lt;p&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%2Flkbif67av38p998fcl5u.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%2Flkbif67av38p998fcl5u.png" alt="Union" width="800" height="178"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So unions allow us to access the same memory bits as different types. This is exactly what we want, and unlike the pointer method, it's allowed by the C standard (but not in C++, by the way).&lt;/p&gt;

&lt;p&gt;Accessing a float's bits can now be simplified using our &lt;code&gt;Bits&lt;/code&gt; union:&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="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;f&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="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;Bits&lt;/span&gt; &lt;span class="n"&gt;bits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{.&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&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;size_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="mi"&gt;32&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="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;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;8&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="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;" "&lt;/span&gt;&lt;span class="p"&gt;);&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;bit_ix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;31&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="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;bit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bit_ix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&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;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%u"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bit&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;"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this is the way I like to do it.&lt;/p&gt;

&lt;p&gt;So let's put this into a reusable function &lt;code&gt;print_float_bits&lt;/code&gt; where we pass in a float and get it to print the 32 bits to the console.&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="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;print_float_bits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;f&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;"%f -&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;Bits&lt;/span&gt; &lt;span class="n"&gt;bits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{.&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&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;size_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="mi"&gt;32&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="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;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;8&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="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;" "&lt;/span&gt;&lt;span class="p"&gt;);&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;bit_ix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;31&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="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;bit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bit_ix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;1u&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;"%u"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bit&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;"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function prints out the float first, then the 32 bits (4 bytes) that make up this float:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;1.000000 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;00111111 10000000 00000000 00000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Experiments
&lt;/h2&gt;

&lt;p&gt;Before doing any experimentation, the one thing I know about floating-point numbers is that they use sort of a binary version of scientific notation. Scientific notation is some coefficient &lt;code&gt;c&lt;/code&gt;, multiplied by 10 to the power of some exponent &lt;code&gt;e&lt;/code&gt;: &lt;code&gt;c × 10^e&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The binary version is simply &lt;code&gt;c × 2^e&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This means that if you increase the exponent by 1, the final number is doubled.&lt;/p&gt;

&lt;p&gt;So let's see what happens if we print 0.5, 1.0, and keep doubling a few more times:&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="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;floats&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;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&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="n"&gt;f&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;0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;f&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;0&lt;/span&gt;&lt;span class="n"&gt;f&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;size_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="k"&gt;sizeof&lt;/span&gt; &lt;span class="n"&gt;floats&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;floats&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="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;print_float_bits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;floats&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;0.500000 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;00111111 00000000 00000000 00000000
&lt;span class="gp"&gt;1.000000 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;00111111 10000000 00000000 00000000
&lt;span class="gp"&gt;2.000000 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;01000000 00000000 00000000 00000000
&lt;span class="gp"&gt;4.000000 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;01000000 10000000 00000000 00000000
&lt;span class="gp"&gt;8.000000 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;01000001 00000000 00000000 00000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you look closely at the bits, you can see there is a certain sequence of bits that keeps incrementing as we're doubling the float (the first 9 bits). The 9th bit has this 0-1-0-1 even/odd flipping pattern.&lt;/p&gt;

&lt;p&gt;These might be the exponent bits we're seeing.&lt;/p&gt;

&lt;p&gt;Another interesting thing we can do is look at 1.0, then double it to 2.0, then take the bits of 2.0 as an integer and subtract one. This should give us the highest possible float below 2.0.&lt;/p&gt;

&lt;p&gt;To see this better, I'm increasing the number of decimal places to 8 like so:&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="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;"% .8f -&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&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;Note that I'm also adding a space in the format (&lt;code&gt;% .8f&lt;/code&gt;). This reserves a space for the &lt;code&gt;-&lt;/code&gt; sign, even if we have a positive number, which keeps all the numbers aligned.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt; 1.00000000 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;00111111 10000000 00000000 00000000
&lt;span class="gp"&gt; 1.99999988 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;00111111 11111111 11111111 11111111
&lt;span class="gp"&gt; 2.00000000 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;01000000 00000000 00000000 00000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you look at the bits, the 1.0 and the 1.999... float both seem to have the same exponent bits, but in the 1.999... version, all the trailing zeros have flipped to ones.&lt;/p&gt;

&lt;p&gt;Looking at this, it would make sense that all these bits that were flipped between 1.0 and 1.999... are the coefficient bits, or "mantissa" bits.&lt;/p&gt;

&lt;p&gt;How about negative numbers? We can easily test a bunch of negative numbers, and see what happens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt; 1.00000000 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;00111111 10000000 00000000 00000000
&lt;span class="gp"&gt;-1.00000000 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;10111111 10000000 00000000 00000000
&lt;span class="gp"&gt; 1.50000000 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;00111111 11000000 00000000 00000000
&lt;span class="gp"&gt;-1.50000000 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;10111111 11000000 00000000 00000000
&lt;span class="gp"&gt; 2.00000000 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;01000000 00000000 00000000 00000000
&lt;span class="gp"&gt;-2.00000000 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;11000000 00000000 00000000 00000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seems like it's the first bit. If it's 0, the number is positive; if it's a 1, the number is negative.&lt;/p&gt;

&lt;p&gt;This rule even holds true for the number 0.0:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt; 0.00000000 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;00000000 00000000 00000000 00000000
&lt;span class="gp"&gt;-0.00000000 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;10000000 00000000 00000000 00000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might have seen negative zero (-0.0) floating around in terminal outputs. This is where it comes from: there is a literal negative zero float, distinct from the normal zero.&lt;/p&gt;

&lt;p&gt;If we check for equality, the program says they are equal, which makes sense. But I wouldn't have been surprised if it had said false. It's generally not a good idea to compare floats for equality.&lt;/p&gt;

&lt;p&gt;So, what we've found is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The highest (leftmost) bit is the sign&lt;/li&gt;
&lt;li&gt;The next 8 highest bits are the exponent&lt;/li&gt;
&lt;li&gt;The last (lowest) 23 bits are the coefficient (a.k.a. mantissa)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Fancy terminal colors
&lt;/h2&gt;

&lt;p&gt;Now that we know each bit's role, we can give them different colors.&lt;/p&gt;

&lt;p&gt;In C, these are some macros I use to be able to print a few terminal colors:&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;#define ESC "\033"
#define RESET ESC "[0m"
#define FG_GRN ESC "[32m"
#define FG_YEL ESC "[33m"
#define FG_CYA ESC "[36m"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in the &lt;code&gt;print_float_bits&lt;/code&gt; function, I'm using them like this:&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="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;print_float_bits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;f&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;"% .8f -&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;Bits&lt;/span&gt; &lt;span class="n"&gt;bits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{.&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&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;size_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="mi"&gt;32&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="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;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;8&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="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;" "&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;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="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="n"&gt;FG_YEL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;i&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="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="n"&gt;FG_GRN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;9&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="n"&gt;FG_CYA&lt;/span&gt;&lt;span class="p"&gt;);&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;bit_ix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;31&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="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;bit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bit_ix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;1u&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;"%u"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bit&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="n"&gt;RESET&lt;/span&gt; &lt;span class="s"&gt;"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prints out floats like this:&lt;/p&gt;

&lt;p&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%2F9b8w3ji9cfxs5uhy2veo.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%2F9b8w3ji9cfxs5uhy2veo.png" alt="Terminal colors" width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yellow is the sign bit, the exponent bits are green, and the mantissa is blue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decoding the bits
&lt;/h2&gt;

&lt;p&gt;We now know which bits do what, but how do they combine into the actual number? There are two small tricks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The exponent is stored with a &lt;em&gt;bias&lt;/em&gt; of 127. So the real exponent is the stored value
minus 127. For 1.0, the exponent bits are &lt;code&gt;01111111&lt;/code&gt; = 127, and 127 - 127 = 0.&lt;/li&gt;
&lt;li&gt;The coefficient always starts with an invisible &lt;code&gt;1.&lt;/code&gt; in front of it, because in binary
scientific notation, the leading digit is always 1 anyway. So there's no point in
storing it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Put together:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;value = (-1)^sign × 1.mantissa × 2^(exponent - 127)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Let's check 1.5: the sign is 0, the exponent bits are 127 (so 2^0 = 1), and the mantissa bits are &lt;code&gt;1000...&lt;/code&gt;, which makes the coefficient &lt;code&gt;1.1&lt;/code&gt; in binary. That's 1 + 1/2 = 1.5. So we get 1 × 1.5 × 1 = 1.5.&lt;/p&gt;

&lt;h2&gt;
  
  
  Special floats
&lt;/h2&gt;

&lt;p&gt;We've been defining floats, and then looking at their binary representation.&lt;/p&gt;

&lt;p&gt;How about we flip it: define some bits, and look at which float we get? We can define integers in binary format using the &lt;code&gt;0b...&lt;/code&gt; syntax. This is officially part of C since C23, but GCC and Clang have supported it as an extension for much longer.&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;Bits&lt;/span&gt; &lt;span class="n"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;b00000000000000000000000000000000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;print_float_bits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt; 0.00000000 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;00000000 00000000 00000000 00000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we set all bits to 0, we get a float of 0.0. We already knew this.&lt;/p&gt;

&lt;p&gt;How about we flip all bits to 1s?&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;bits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;b11111111111111111111111111111111&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;print_float_bits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;nan -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;11111111 11111111 11111111 11111111
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We get &lt;code&gt;nan&lt;/code&gt;! (On Linux you might see &lt;code&gt;-nan&lt;/code&gt;, because the sign bit is set.)&lt;/p&gt;

&lt;p&gt;Let's see what we get if we only set the exponent bits to 1:&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;bits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;b01111111100000000000000000000000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;print_float_bits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt; inf -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;01111111 10000000 00000000 00000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We get &lt;code&gt;inf&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;Can we flip the sign of &lt;code&gt;inf&lt;/code&gt;? Let's try setting the highest bit to 1:&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;bits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;b11111111100000000000000000000000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;print_float_bits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;-inf -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;11111111 10000000 00000000 00000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, we can :) So as you can see, all those strange flavors of numbers like &lt;code&gt;nan&lt;/code&gt; and &lt;code&gt;inf&lt;/code&gt; are nothing more than specific bit patterns.&lt;/p&gt;




&lt;p&gt;That's where I'll leave it for now. I hope that was helpful. I much prefer this method of exploration by hacking away at them, instead of reading the documentation.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://vanderoost.com/articles/2026/10/02/how-floats-work/" rel="noopener noreferrer"&gt;vanderoost.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>c</category>
      <category>computerscience</category>
      <category>learning</category>
      <category>programming</category>
    </item>
    <item>
      <title>Stop using rand()</title>
      <dc:creator>Richard</dc:creator>
      <pubDate>Fri, 25 Sep 2026 12:34:11 +0000</pubDate>
      <link>https://dev.to/vanderoost/stop-using-rand-166a</link>
      <guid>https://dev.to/vanderoost/stop-using-rand-166a</guid>
      <description>&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/-5NqTA-fDNQ" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In this article I will try to convince you to stop using &lt;code&gt;rand()&lt;/code&gt; in your C projects, and write a better alternative from scratch.&lt;/p&gt;

&lt;p&gt;Before I entered the RNG rabbit hole, I was definitely guilty of grabbing &lt;code&gt;rand()&lt;/code&gt;, and maybe some &lt;code&gt;srand(time(NULL))&lt;/code&gt; when I needed it to be "unpredictable".&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"But I'm not using it for cryptography"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the back of my mind I always knew that &lt;code&gt;rand()&lt;/code&gt; was not a "safe" random number generator, but when you just need some randomness for statistics or machine learning, who cares?&lt;/p&gt;

&lt;p&gt;After digging a bit deeper though, I found out stronger reasons for ditching &lt;code&gt;rand()&lt;/code&gt; and using something better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not?
&lt;/h2&gt;

&lt;p&gt;The three main reasons I don't use &lt;code&gt;rand()&lt;/code&gt; anymore:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It's platform dependent&lt;/li&gt;
&lt;li&gt;It's slow&lt;/li&gt;
&lt;li&gt;It's low quality&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Platform dependent
&lt;/h3&gt;

&lt;p&gt;This means that &lt;code&gt;rand()&lt;/code&gt; behaves differently depending on the platform you compile it for. What might be different? The maximum random number you can get (&lt;code&gt;RAND_MAX&lt;/code&gt;) might be different, also the sequence of random numbers after a given seed set with &lt;code&gt;srand()&lt;/code&gt; can be different. So that can be pretty annoying.&lt;/p&gt;

&lt;h3&gt;
  
  
  Slow
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;rand&lt;/code&gt; function is not doing any complex math, but it relies on a &lt;em&gt;global state&lt;/em&gt; and needs to acquire a lock to be able to mutate it (at least my implementation on MacOS). This happens every time you call &lt;code&gt;rand()&lt;/code&gt;. So when you're calling it in a hot loop, it can get pretty slow compared to rolling your own RNG.&lt;/p&gt;

&lt;h3&gt;
  
  
  Low quality
&lt;/h3&gt;

&lt;p&gt;The quality of random numbers that &lt;code&gt;rand()&lt;/code&gt; produces is poor, we already knew that it's not "cryptographically safe" to use. But if we look at some simple alternatives, we can easily get way higher quality random numbers. (longer periods for example, so less repetition in sequences)&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting &lt;code&gt;rand()&lt;/code&gt; to the test
&lt;/h2&gt;

&lt;p&gt;Humans are pretty good at recognizing visual patterns. So to test a random number generator, you can use visualization to expose flaws. Let's do that with &lt;code&gt;rand()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If we create a 960 × 540 pixel buffer, and pick random color values for each pixel using &lt;code&gt;rand()&lt;/code&gt;:&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;#define WIDTH 960
#define HEIGHT 540
#define DEPTH 3 // RGB
&lt;/span&gt;
&lt;span class="cp"&gt;#define BUF_LEN (WIDTH * HEIGHT * DEPTH)
&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="p"&gt;)&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;pix_buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;BUF_LEN&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="k"&gt;for&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;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;WIDTH&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;HEIGHT&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pixel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pix_buffer&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;*&lt;/span&gt; &lt;span class="n"&gt;DEPTH&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;roll&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rand&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;pixel_col&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;roll&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RAND_MAX&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="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pixel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pixel_col&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DEPTH&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Writing the pixels to an image here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(if you want to know how to write the pixels to an image, I cover it in the &lt;a href="https://youtu.be/-5NqTA-fDNQ?t=472" rel="noopener noreferrer"&gt;video&lt;/a&gt; and you can see the code in the &lt;a href="https://github.com/vanderoost/rng.c/blob/main/src/rng_image.c#L36-L46" rel="noopener noreferrer"&gt;repository&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We get an image that looks like this:&lt;/p&gt;

&lt;p&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%2Fqoibky3cc1dj1lmjizs4.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%2Fqoibky3cc1dj1lmjizs4.png" alt="Simple random pixels" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looks pretty random, no weird patterns or repetition.&lt;/p&gt;

&lt;p&gt;But if we change the way we color in the pixels, we can push &lt;code&gt;rand()&lt;/code&gt; to its limits.&lt;/p&gt;

&lt;p&gt;Instead of looping over pixels, we'll take a certain amount of "samples". For every sample, we pick a random number to decide which pixel to color, then we pick another random number that decides the color for that pixel:&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;#define SAMPLE_COUNT (1 &amp;lt;&amp;lt; 20)
&lt;/span&gt;
&lt;span class="cp"&gt;#define WIDTH 960
#define HEIGHT 540
#define DEPTH 3 // RGB
&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="p"&gt;)&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;pix_buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;BUF_LEN&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="k"&gt;for&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;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;SAMPLE_COUNT&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;roll_a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rand&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;roll_b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rand&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;pixel_ix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;roll_a&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RAND_MAX&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="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;WIDTH&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;HEIGHT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pixel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pix_buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pixel_ix&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;DEPTH&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;pixel_col&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;roll_b&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RAND_MAX&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="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pixel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pixel_col&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DEPTH&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Writing the pixels to an image here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this is the image you get:&lt;/p&gt;

&lt;p&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%2Fx29c2nwkozl811jozen2.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%2Fx29c2nwkozl811jozen2.png" alt="Random stripes pattern" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looks okay at first glance, but if you zoom in you can clearly start to see some repetition:&lt;/p&gt;

&lt;p&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%2F52osy9ncx7zasjnlyps7.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%2F52osy9ncx7zasjnlyps7.png" alt="Random stripes pattern zoomed" width="192" height="108"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The reason for this pattern is that we call &lt;code&gt;rand()&lt;/code&gt; once for the position, and then again for the color. And if you call &lt;code&gt;rand()&lt;/code&gt; twice, the second call really depends on the first call. So in this loop, the color depends on the location, that's what causes the stripe pattern.&lt;/p&gt;

&lt;p&gt;So, &lt;code&gt;rand()&lt;/code&gt; is clearly suboptimal. How can we improve it?&lt;/p&gt;

&lt;h2&gt;
  
  
  What about &lt;code&gt;random()&lt;/code&gt; ?
&lt;/h2&gt;

&lt;p&gt;There is a better alternative than &lt;code&gt;rand()&lt;/code&gt; available, called &lt;code&gt;random()&lt;/code&gt;. And yes, it gives better quality random numbers, it's also faster (compared on an M2 Mac).&lt;/p&gt;

&lt;p&gt;But after diving into the alternatives, writing my own RNG function seemed so much more interesting that I went for that. And by writing it from scratch, we will still end up with a 2.7 times faster function that has twice the range (32 bits instead of 31). So rolling our own RNG is still a good idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  RNG from first principles
&lt;/h2&gt;

&lt;p&gt;I'd like to get a basic understanding of how a pseudo random number generator works.&lt;/p&gt;

&lt;p&gt;There are a lot of different approaches for generating random numbers. Most of them share the basic principle of having some kind of &lt;strong&gt;state&lt;/strong&gt;, and being able to &lt;strong&gt;scramble&lt;/strong&gt; this state to make it appear "random".&lt;/p&gt;

&lt;p&gt;The random number you get when you call the generator is based on this state, and every time you generate a random number, the state gets mutated. So the next time you generate a random number, you will get a different one.&lt;/p&gt;

&lt;p&gt;With this in mind, the most basic example of a pseudo random number generator might be something like this:&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;static&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;rng_state&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;uint32_t&lt;/span&gt; &lt;span class="nf"&gt;rng_u&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&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="n"&gt;rng_state&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="mi"&gt;12343&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;It has a state &lt;code&gt;rng_state&lt;/code&gt;, and it "scrambles" this state by multiplying it by some constant &lt;code&gt;12343&lt;/code&gt;. I just picked an arbitrary 5 digit prime number for this. My intuition is that prime numbers avoid any obvious repetition.&lt;/p&gt;

&lt;p&gt;The list of "random" numbers this thing generates looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;12343
152349649
3551009255
4260946081
982938263
3419336305
2519362119
923411777
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even this basic example looks pretty random at first glance. But of course, you can see that the first number is exactly our factor &lt;code&gt;12343&lt;/code&gt; and we multiply by this amount every time, until we wrap around back to &lt;code&gt;0&lt;/code&gt; at &lt;code&gt;4,294,967,296&lt;/code&gt; (2³²).&lt;/p&gt;

&lt;p&gt;This also means that we never generate an even number. So there are plenty of flaws to this approach. But this is the basic principle: a state that gets scrambled. We just need to "scramble" it a bit better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Larger state and better scrambling
&lt;/h2&gt;

&lt;p&gt;What also helps, is to reserve more bytes for the state. It's generally a good idea to have more bytes of state than the bytes of the random number you want to generate. So if you want to generate 32-bit random numbers, having a state of 64 bits would be a good idea.&lt;/p&gt;

&lt;p&gt;Getting the optimal scrambling is a wheel I'd rather not re-invent myself. So I've searched for robust existing methods that have proved to behave well, and are backed by research and testing.&lt;/p&gt;

&lt;p&gt;The best approach I've found in terms of simplicity, performance, and quality, is the &lt;a href="https://pcg-random.org" rel="noopener noreferrer"&gt;PCG family&lt;/a&gt;. On that website, they share a basic C implementation that looks like this:&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;// *Really* minimal PCG32 code / (c) 2014 M.E. O'Neill / pcg-random.org&lt;/span&gt;
&lt;span class="c1"&gt;// Licensed under Apache License 2.0 (NO WARRANTY, etc. see website)&lt;/span&gt;

&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="n"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;pcg32_random_t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="nf"&gt;pcg32_random_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pcg32_random_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;rng&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="n"&gt;oldstate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rng&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Advance internal state&lt;/span&gt;
    &lt;span class="n"&gt;rng&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;oldstate&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;6364136223846793005ULL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rng&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;inc&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="c1"&gt;// Calculate output function (XSH RR), uses old state for max ILP&lt;/span&gt;
    &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;xorshifted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;oldstate&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;18u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;oldstate&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;27u&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;rot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;oldstate&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;59u&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xorshifted&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;rot&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;xorshifted&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;rot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;31&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;As you can see, for the state we use a struct called &lt;code&gt;pcg32_random_t&lt;/code&gt; that holds two 64-bit integers, one is the actual &lt;code&gt;state&lt;/code&gt;, the other decides which "path" or "trajectory" we take through the state.&lt;/p&gt;

&lt;p&gt;Calling the function &lt;code&gt;pcg32_random_r&lt;/code&gt; scrambles the state properly, better than simply multiplying it by a constant number.&lt;/p&gt;

&lt;p&gt;In order to use this minimal example, we need to declare our global state. The minimal C example only defines a struct, but it's never instantiated. We can grab the following from their &lt;a href="https://github.com/imneme/pcg-c-basic" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;:&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;#define PCG32_INITIALIZER {0x853c49e6748fea9bULL, 0xda3e39cb94b95bdbULL}
&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;pcg32_random_t&lt;/span&gt; &lt;span class="n"&gt;pcg32_global&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PCG32_INITIALIZER&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we actually have a global state called &lt;code&gt;pcg32_global&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To generate a random number, we have to call the function &lt;code&gt;pcg32_random_r&lt;/code&gt; and pass it the address of our global state:&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="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;roll&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pcg32_random_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pcg32_global&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Adding some useful wrappers
&lt;/h2&gt;

&lt;p&gt;When I need a random number, I just want to call a simple function, and not worry about passing it anything. So let's add a simple wrapper that allows us to do this:&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="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="nf"&gt;rng_u&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&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="n"&gt;pcg32_random_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pcg32_global&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;Now we can simply call &lt;code&gt;rng_u()&lt;/code&gt; to get a random &lt;code&gt;uint32_t&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This adds a bit of indirection, which can slow down the code. So later on we'll look at inlining &lt;code&gt;rng_u()&lt;/code&gt; and &lt;code&gt;pcg32_random_r()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In addition to random integers, I'd like to get random floats too. Let's add a &lt;code&gt;float rng_f(void)&lt;/code&gt;:&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="kt"&gt;float&lt;/span&gt; &lt;span class="nf"&gt;rng_f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&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="n"&gt;pcg32_random_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pcg32_global&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;UINT32_MAX&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're dividing by &lt;code&gt;UINT32_MAX + 1.0f&lt;/code&gt; to make sure we get a range from 0 to 1 but excluding &lt;code&gt;1.0&lt;/code&gt;. So the range we get is &lt;code&gt;[0.0, 1.0)&lt;/code&gt;. This is typically the most convenient 0 - 1 range to work with for most use cases where you need a random float.&lt;/p&gt;

&lt;p&gt;Getting a random float this way is quite naive and can be improved a lot, which we will do in a future article. So stay tuned if that's something you'd like to see.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sampling from a normal distribution
&lt;/h2&gt;

&lt;p&gt;We can add another flavor of random floats: a random float sampled from a normal distribution. This can be very useful in machine learning and statistics.&lt;/p&gt;

&lt;p&gt;If we look at a histogram of 1M random floats, it looks quite uniform:&lt;/p&gt;

&lt;p&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%2Fiq5v5h6i2882queck6he.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%2Fiq5v5h6i2882queck6he.png" alt="Uniform RNG histogram" width="800" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can get some interesting distributions by playing around with this. For example, we can add two random numbers together, which gives us this pyramid shaped distribution:&lt;/p&gt;

&lt;p&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%2Fxzn1fuup5c8b5dge5lvm.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%2Fxzn1fuup5c8b5dge5lvm.png" alt="Sum of 2 RNGs histogram" width="800" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And if we go a step further, adding three random floats together, we're starting to get something that has the shape of a bell curve:&lt;/p&gt;

&lt;p&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%2Fhimr1n8twp3hvwqswyvf.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%2Fhimr1n8twp3hvwqswyvf.png" alt="Sum of 3 RNGs histogram" width="800" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we add more vanilla random numbers together (random numbers sampled from a uniform distribution), we get closer and closer to a true normal distribution.&lt;/p&gt;

&lt;p&gt;What I want when getting a random "norm" float, is I want it to be sampled from a normal distribution that has a mean of 0.0 and standard deviation of 1.0.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://youtu.be/-5NqTA-fDNQ" rel="noopener noreferrer"&gt;video&lt;/a&gt; I explore this a bit more, but it turns out that if you add 12 random floats together that were sampled from a uniform distribution between 0 and 1, you end up with a standard deviation of exactly 1.0.&lt;/p&gt;

&lt;p&gt;The mean will be sitting at 12 * 0.5 = 6, so we have to shift the numbers by -6 to get a mean of 0.0.&lt;/p&gt;

&lt;p&gt;This can be wrapped in a function called &lt;code&gt;rng_norm&lt;/code&gt; and we get something like this:&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="kt"&gt;float&lt;/span&gt; &lt;span class="nf"&gt;rng_norm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&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;0&lt;/span&gt;&lt;span class="n"&gt;f&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;size_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="mi"&gt;12&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="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;rng_f&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="n"&gt;result&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 function builds upon our &lt;code&gt;rng_f&lt;/code&gt; function, which isn't as optimal as I'd like yet. And moreover, it calls it a whopping 12 times, which isn't quite optimal either if you run it in a hot loop. So even though this kind of works, and gets you a pseudo normally distributed sample, we will look at optimizing &lt;code&gt;rng_f&lt;/code&gt; and &lt;code&gt;rng_norm&lt;/code&gt; more in a future article.&lt;/p&gt;

&lt;p&gt;In this article let's keep the focus on our &lt;code&gt;rand()&lt;/code&gt; replacement &lt;code&gt;rng_u()&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optimizing &lt;code&gt;rng_u()&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Our vanilla random integer generator has a bunch of indirection. One way we can optimize it is by inlining both &lt;code&gt;rng_u&lt;/code&gt; and &lt;code&gt;pcg32_random_r&lt;/code&gt;:&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;static&lt;/span&gt; &lt;span class="kr"&gt;inline&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="nf"&gt;pcg32_random_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pcg32_random_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;rng&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="n"&gt;oldstate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rng&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// LCG step (pcg_setseq_64_step_r)&lt;/span&gt;
  &lt;span class="n"&gt;rng&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;oldstate&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;6364136223846793005ULL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rng&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;inc&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="c1"&gt;// XSH RR output (pcg_output_xsh_rr_64_32), fed the old state so the&lt;/span&gt;
  &lt;span class="c1"&gt;// step and the output function can overlap&lt;/span&gt;
  &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;xorshifted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;oldstate&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;18u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;oldstate&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;27u&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;rot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;oldstate&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;59u&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xorshifted&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;rot&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;xorshifted&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;rot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kr"&gt;inline&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="nf"&gt;rng_u&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&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="n"&gt;pcg32_random_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pcg32_global&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;There's a little bit more to this if you want to stash the RNG code away into a lib with a &lt;code&gt;.c&lt;/code&gt; and &lt;code&gt;.h&lt;/code&gt;. See the &lt;a href="https://github.com/vanderoost/rng.c" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; for more details, as I might keep that more up to date than this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;What this gives us, is a proper &lt;code&gt;rand()&lt;/code&gt; alternative where we have 100% control over the code, no dependencies.&lt;/p&gt;

&lt;p&gt;So what does the random image look like that we get out of this new implementation?&lt;/p&gt;

&lt;p&gt;Properly random like this:&lt;/p&gt;

&lt;p&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%2F23pfyhg5cjqmkkp2ufdl.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%2F23pfyhg5cjqmkkp2ufdl.png" alt="Random pixels with rng_u" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And no patterns or repetition to be seen when we zoom in either:&lt;/p&gt;

&lt;p&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%2Fv9ek6z6isgu8brehsgjc.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%2Fv9ek6z6isgu8brehsgjc.png" alt="Random pixels with rng_u zoomed in" width="192" height="108"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How about the execution time?&lt;/p&gt;

&lt;p&gt;I've written a more elaborate benchmark script that compares &lt;code&gt;rand()&lt;/code&gt; with &lt;code&gt;rng_u()&lt;/code&gt; (can be found in the &lt;a href="https://github.com/vanderoost/rng.c" rel="noopener noreferrer"&gt;repo&lt;/a&gt; as well).&lt;/p&gt;

&lt;p&gt;This is the result on an M2 Macbook Pro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;rand    6.651 ns/call
random  2.760 ns/call
rng_u   1.016 ns/call
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our own implementation &lt;code&gt;rng_u()&lt;/code&gt; is roughly 6.5 times faster than &lt;code&gt;rand()&lt;/code&gt; (and 2.7 times faster than &lt;code&gt;random()&lt;/code&gt;). Not bad!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://vanderoost.com/articles/2026/09/25/stop-using-rand/" rel="noopener noreferrer"&gt;vanderoost.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>c</category>
      <category>coding</category>
      <category>programming</category>
    </item>
    <item>
      <title>Why 95% of company AI projects fail</title>
      <dc:creator>Richard</dc:creator>
      <pubDate>Sun, 20 Sep 2026 13:26:17 +0000</pubDate>
      <link>https://dev.to/vanderoost/why-95-of-company-ai-projects-fail-1614</link>
      <guid>https://dev.to/vanderoost/why-95-of-company-ai-projects-fail-1614</guid>
      <description>&lt;p&gt;It's an interesting time to be alive. The "AI transformation" is happening.&lt;/p&gt;

&lt;p&gt;Many business owners feel FOMO on AI adoption. Yet, allegedly 95% of AI projects in companies fail, according to an MIT report. Why is this?&lt;/p&gt;

&lt;p&gt;I've talked to business owners and AI automation agencies. This is what I found.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenge: GenAI is non-deterministic
&lt;/h2&gt;

&lt;p&gt;This is the big one. If you think like a software engineer, AI is finicky / fuzzy compared to cold hard code. LLM's use a literal random number generator to produce their outputs.&lt;/p&gt;

&lt;p&gt;So if you use LLM's for automation, you will have unexpected things happening.&lt;/p&gt;

&lt;p&gt;Most of the risk surfaces when you're using &lt;strong&gt;AI Agents&lt;/strong&gt; to automate tasks. But there is a more boring and deterministic approach to automation: &lt;strong&gt;AI workflows&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Agents vs. AI Workflows
&lt;/h2&gt;

&lt;p&gt;These are the two main approaches to AI automation.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI Agents
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Agents&lt;/strong&gt; [] are systems where LLMs dynamically direct their own processes and tool usage, maintaining control over how they accomplish tasks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is currently the most hyped up version of automation:&lt;/p&gt;

&lt;p&gt;Trigger an LLM, and let it run wild with tools.&lt;/p&gt;

&lt;p&gt;And by "let it run wild with tools" I mean:&lt;/p&gt;

&lt;p&gt;Give it a sense of which tools it can use, and let the LLM decide which tools it wants to call, and how.&lt;/p&gt;

&lt;p&gt;Tools can be: reading / writing files on your computer, using a calculator, doing web search. Anything you might be able to do with a computer that could be useful for the task at hand.&lt;/p&gt;

&lt;p&gt;The flexible "blank canvas" approach here makes it quite interesting, but every little mistake adds up, and over time, results can get wild. This is not what you want in a company procedure.&lt;/p&gt;

&lt;p&gt;So it currently requires a lot of babysitting to be productive with agents, which kind of defeats the purpose of automation.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI Workflows
&lt;/h3&gt;

&lt;p&gt;Less flashy, more simple and deterministic.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Workflows&lt;/strong&gt; are systems where LLMs and tools are orchestrated through predefined code paths.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;AI workflows are simple software procedures, with deterministic logic. The are "set in stone" and designed upfront with a lot of care.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Being predefined makes them less flexible, but that's exactly what you want in a company with SOP's. Only where it makes sense, LLM calls are made.&lt;/p&gt;

&lt;p&gt;This way, you keep the automation in check, and things don't spiral out of control by a hallucinating model.&lt;/p&gt;

&lt;p&gt;Every LLM call has guardrails with enforced checks and fallbacks. So even if an LLM model completely shits the bed, your workflow can still move on in a reasonable way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recipes for failure
&lt;/h2&gt;

&lt;p&gt;The common patterns of AI projects that fail are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;One system trying to automate everything&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automating workflows that still need human feedback&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Architecting high level production systems&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  One system trying to automate everything
&lt;/h3&gt;

&lt;p&gt;The man who chases two rabbits, catches none. If you try to automate too much with a single system, the chances of failure increase geometrically. And that is why it so often fails.&lt;/p&gt;

&lt;p&gt;The better approach is to take one procedure at a time, something that is done manually so you know exactly what needs to be done. You know the exceptions, you know the intricate details. Then it's a lot easier to start building an automation for this.&lt;/p&gt;

&lt;p&gt;Don't "automate the marketing" for your company, but automate budgeting your google ads account for example.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automating workflows that still need human feedback
&lt;/h3&gt;

&lt;p&gt;If you try to fully automate a workflow where you should be checking things before moving to the next step, you're gonna have a bad time.&lt;/p&gt;

&lt;p&gt;For example, sending emails. If you think your agent can read incoming emails, figure out a reply, and send them off. This might work well for 90% of the cases. But unexpected situations can cause massive disasters.&lt;/p&gt;

&lt;p&gt;Solution: Automate 95% of the process, but have a human give the final green light before moving on. So let the AI draft a reply, you're the one to send it off.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Architecting high level production systems&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI models wrapped up in coding harnesses are getting extremely good at software engineering. But when architecting high level production systems, AI currently just lacks some of the awareness, company history, that's required to lead this to a good outcome.&lt;/p&gt;

&lt;p&gt;Solution: Human / agent collaboration. Have a senior engineer go back and forth with the coding agent to come to a good outcome.&lt;/p&gt;

&lt;h2&gt;
  
  
  What works well
&lt;/h2&gt;

&lt;p&gt;As we'll see, the non-deterministic nature of genAI explains why it so often fails to automate a business procedure.&lt;/p&gt;

&lt;p&gt;The common theme is that typically the more boring automations, that don't look exciting or flashy, are working the best.&lt;/p&gt;

&lt;p&gt;This agrees with Anthropic's take on the matter:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;we recommend finding the simplest solution possible, and only increasing complexity when needed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After talking to business owners, these are some AI project areas that are either working well or failing miserably.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data analytics
&lt;/h3&gt;

&lt;p&gt;Most companies are collecting data. And LLM's are fantastic at pulling data from a database, and drawing conclusion.&lt;/p&gt;

&lt;p&gt;Especially if you give it the proper context of what they have access to, and all the relations between entities.&lt;/p&gt;

&lt;p&gt;This can be a great way to answer business questions with subtle nuances that are different every time. For example, a question like: "What was last quarter's revenue from returning European customers?" and "How many of them spent over $1,000?".&lt;/p&gt;

&lt;p&gt;This used to take a MySQL (or Tableau/Power BI) expert and a complicated query for every single question.&lt;/p&gt;

&lt;p&gt;Now, most state of the art LLM's are smart enough to connect the dots, and pull the correct data out.&lt;/p&gt;

&lt;p&gt;Pro tip: Give the LLM read-only access to your database. For analytics there's no need to change the database. We've all heard the horror stories of "the AI wiped out production".&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Specialised translation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;LLM's are pretty good at language. So if you have a specific translation job to do, where context matters a lot, they can do a great job.&lt;/p&gt;

&lt;p&gt;If context matters a lot, you do have to make sure to give that context to the LLM, obviously.&lt;/p&gt;

&lt;p&gt;Examples of this could be: Translating restaurant menu's into different languages. Here, it's important to not translate everything literally, but now that everything is food related. And if a menu item says "Margarita" it's important to know whether it's under the pizza's or the cocktails section.&lt;/p&gt;

&lt;p&gt;Another example could be: Translating subtitles for technical tutorial videos. Having the context of the technical topic, and jargon is important here. But once you give it this context, LLMs can be great.&lt;/p&gt;

&lt;p&gt;This is a perfect example of where a workflow performs a lot better than agents.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Research&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;LLMs are great at processing large amounts of text. If you need to do research on a certain topic, you can let LLMs search the internet for sources, and cross reference different findings.&lt;/p&gt;

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

&lt;p&gt;AI projects tend to fail because companies try to hastily adopt new workflows out of fear of missing out, and by nature, LLMs are non-deterministic.&lt;/p&gt;

&lt;p&gt;The approach that works reliably is: keeping it simple.&lt;/p&gt;

&lt;p&gt;When building applications with LLMs, use the simplest solution possible, and only increase complexity when needed.&lt;/p&gt;

&lt;p&gt;This might mean not building "agentic" systems at all, but just stick to workflows.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://vanderoost.com/articles/2026/09/13/why-company-ai-projects-fail/" rel="noopener noreferrer"&gt;vanderoost.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Plotting histograms in the terminal</title>
      <dc:creator>Richard</dc:creator>
      <pubDate>Sun, 20 Sep 2026 13:26:16 +0000</pubDate>
      <link>https://dev.to/vanderoost/plotting-histograms-in-the-terminal-4hkg</link>
      <guid>https://dev.to/vanderoost/plotting-histograms-in-the-terminal-4hkg</guid>
      <description>&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/aLNlyBNU0tw" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;I was generating some random numbers the other day. And I really felt the urge to visualize them. Just to get an intuition, like, what's the shape of the distribution? Is it noisy or smooth?&lt;/p&gt;

&lt;p&gt;When in Python, I would usually bust out &lt;code&gt;pip install matplotlib&lt;/code&gt; for this kind of tech. But what are the options when you're in C?&lt;/p&gt;

&lt;p&gt;I ended up writing a plot library from scratch of course :) &lt;a href="https://github.com/vanderoost/plt.c" rel="noopener noreferrer"&gt;plt.c on github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I wanted to keep it super simple, so I chose to plot in the terminal, using unicode block characters. No need for external graphics or imaging libraries.&lt;/p&gt;

&lt;p&gt;This is what it looks like:&lt;/p&gt;

&lt;p&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%2Fqkhlw3tul0t1338m9ox9.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%2Fqkhlw3tul0t1338m9ox9.png" alt="Terminal plot example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the rest of this article, we'll walk through the process of writing this library.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generating test data
&lt;/h2&gt;

&lt;p&gt;Before we can plot anything, we need something to plot. I want my utility to work with simple float arrays. If we need other datatypes later we can always do this.&lt;/p&gt;

&lt;p&gt;So let's generate some random floats:&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;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="cp"&gt;#define SAMPLE_COUNT 16
&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="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SAMPLE_COUNT&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;size_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;SAMPLE_COUNT&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="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;data&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="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;RAND_MAX&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="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;
  
  
  Histogram buckets
&lt;/h2&gt;

&lt;p&gt;To take a list of random numbers, and turn it into a histogram, we need to decide on our "buckets".&lt;/p&gt;

&lt;p&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%2Fxz5l0jbh593fpgj4ond6.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%2Fxz5l0jbh593fpgj4ond6.png" alt="Histogram buckets"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's say all the little green dots are our random numbers, or samples. The buckets are drawn as columns, and we just have to count how many samples fall in each bucket. Those counts will correspond to the bar heights of our histogram.&lt;/p&gt;

&lt;p&gt;We can do that by looping over all samples:&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;#define COLS 10
&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;buckets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;COLS&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="k"&gt;for&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;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;SAMPLE_COUNT&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;bucket_ix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&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="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;COLS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;buckets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;bucket_ix&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We initialize our &lt;code&gt;buckets&lt;/code&gt; as a &lt;code&gt;size_t&lt;/code&gt; array, initialized to zero with the &lt;code&gt;= {}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then we loop over all samples, and for each decide which bucket it belongs to. Since we're working with samples from 0.0 to 1.0, it's a simple multiply with the number of columns &lt;code&gt;COLS&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  First ugly plot
&lt;/h2&gt;

&lt;p&gt;Now that we have bucket counts, we can try to plot them. Since we have &lt;em&gt;columns&lt;/em&gt;, we should also introduce the concept of &lt;em&gt;rows&lt;/em&gt;. Rows and columns refer to the terminal characters we can print. So plotting a 2D figure is simply a double loop over rows and columns:&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;#define ROWS 5
&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;size_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;rows&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&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="k"&gt;for&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;j&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;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;cols&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;j&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;buckets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;height&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;"#"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;" "&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="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We hit every cell with our doubly nested loop. Then in each cell we decide whether we're above or below the height/count of the bucket. If we're above, we print a space, if we're below, we print a pound sign. Just an arbitrary character that fills up the cell.&lt;/p&gt;

&lt;p&gt;This spits out:&lt;/p&gt;

&lt;p&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%2F7evf565nk0ka3hdqr1l3.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%2F7evf565nk0ka3hdqr1l3.png" alt="First ugly plot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you squint your eyes, it kind of looks like a histogram..&lt;/p&gt;

&lt;p&gt;But we can do better :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Autoscaling the Y-axis
&lt;/h2&gt;

&lt;p&gt;One big problem with this approach is that we're not scaling the Y-axis at all. So when our sample count increases, we end up plotting a full block where all bars max out.&lt;/p&gt;

&lt;p&gt;This is what it looks like with &lt;code&gt;SAMPLE_COUNT&lt;/code&gt; set to 100:&lt;/p&gt;

&lt;p&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%2F08fifacpbpcnhzq9asto.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%2F08fifacpbpcnhzq9asto.png" alt="Overflowing Y-axis"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can fix this by keeping track of the maximum bucket count:&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="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;bucket_max&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="k"&gt;for&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;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;COLS&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="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;buckets&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="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bucket_max&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;bucket_max&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;buckets&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="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;With this &lt;code&gt;bucket_max&lt;/code&gt; and &lt;code&gt;ROWS&lt;/code&gt;, we can scale the buckets to the right size for our canvas:&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;for&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;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;COLS&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="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;buckets&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="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buckets&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="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ROWS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;bucket_max&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;Multiplying by &lt;code&gt;ROWS&lt;/code&gt;, so increasing our rows will make the bars scale up. Dividing by &lt;code&gt;bucket_max&lt;/code&gt; so the highest bar will always be exactly &lt;code&gt;ROWS&lt;/code&gt; high.&lt;/p&gt;

&lt;p&gt;Now the height of the histogram automatically scales:&lt;/p&gt;

&lt;p&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%2F2kum4vb3vkldf769c6yj.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%2F2kum4vb3vkldf769c6yj.png" alt="Autoscaling the Y-axis"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the full terminal width
&lt;/h2&gt;

&lt;p&gt;We've set our &lt;code&gt;COLS&lt;/code&gt; to an arbitrary 10. We could make the tool really fancy and auto-detect the width of the terminal, but I usually don't change my terminal width much, so I'm ok with just hard-coding it.&lt;/p&gt;

&lt;p&gt;But we can find out our width of the terminal using the &lt;code&gt;$COLUMNS&lt;/code&gt; variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;% echo $&lt;/span&gt;COLUMNS
&lt;span class="go"&gt;72
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So I'll be using 72 from now on. And while we're at it, let's set &lt;code&gt;ROWS&lt;/code&gt; to 16 and also increase the number of samples to 1000:&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;#define SAMPLE_COUNT 1000
#define ROWS 16
#define COLS 72
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now our histogram starts to get a bit more "definition":&lt;/p&gt;

&lt;p&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%2F9m3z69t5tkc7fml5p4m3.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%2F9m3z69t5tkc7fml5p4m3.png" alt="Full-width histogram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Unicode block elements
&lt;/h2&gt;

&lt;p&gt;Instead of the arbitrary pound signs, we can do a lot better. By using &lt;a href="https://en.wikipedia.org/wiki/Block_Elements" rel="noopener noreferrer"&gt;unicode block elements&lt;/a&gt; we can 8x our vertical resolution (without increasing rows).&lt;/p&gt;

&lt;p&gt;We have 8 different block elements, going from 1/8 height (&lt;code&gt;U+2581&lt;/code&gt;), all the way to a full block (&lt;code&gt;U+2588&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;▁ ▂ ▃ ▄ ▅ ▆ ▇ █
1 2 3 4 5 6 7 8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All we have to do now is figure out some logic that prints out the correct unicode characters at the correct spot.&lt;/p&gt;

&lt;p&gt;We will still print one character at a time, so the number of rows and columns doesn't change. But we can now deal with 8 times more height levels.&lt;/p&gt;

&lt;p&gt;And then there are 3 different situations for a character. The column height can either be:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Under the current character: print a space&lt;/li&gt;
&lt;li&gt;Above the current character: print a full block&lt;/li&gt;
&lt;li&gt;Inside the current character: print one of the sub-blocks&lt;/li&gt;
&lt;/ol&gt;

&lt;p&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%2Fnvtz419wkb7un6zo7clv.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%2Fnvtz419wkb7un6zo7clv.png" alt="Three different block situations"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The three situations are drawn in yellow here.&lt;/p&gt;

&lt;p&gt;If we represent all 8 block characters in an array, we can use the index as the "sub-block-height" and we prevent having to write a lot of if-else statements:&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="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;blocks&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="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"\u2581"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"\u2582"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"\u2583"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"\u2584"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"\u2585"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"\u2586"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"\u2587"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"\u2588"&lt;/span&gt;&lt;span class="p"&gt;,&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;block_count&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="n"&gt;blocks&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="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;blocks&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, I've also added the space character in there. So we have a total of 9 elements in our array. I still want to do the math with 8 levels though. So when I calculate &lt;code&gt;block_count&lt;/code&gt; I subtract 1.&lt;/p&gt;

&lt;p&gt;Then when we're autoscaling, we don't want to set the max bucket height equal to &lt;code&gt;ROWS&lt;/code&gt;, but to 8 times &lt;code&gt;ROWS&lt;/code&gt;, so we multiply it by &lt;code&gt;block_count&lt;/code&gt;:&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;for&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;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;cols&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="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;buckets&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="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buckets&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="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;block_count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;bucket_max&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;And then it's time for the plot loop:&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;for&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;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;rows&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&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;block_count&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;size_t&lt;/span&gt; &lt;span class="n"&gt;j&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;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;cols&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;j&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="n"&gt;block_ix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;buckets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;block_ix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;block_ix&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;block_ix&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;block_ix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;block_ix&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;block_count&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;block_count&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;block_ix&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;"%s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;blocks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;block_ix&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;"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our &lt;code&gt;height&lt;/code&gt; is now also multiplied by the &lt;code&gt;block_count&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And then we calculate the index &lt;code&gt;block_ix&lt;/code&gt; which we then have to clamp betwen 0 and 8 to make sure everything works.&lt;/p&gt;

&lt;p&gt;And when we run it like this, we're plotting something that looks like a real histogram:&lt;/p&gt;

&lt;p&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%2F8dn5uphyybpnc784beat.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%2F8dn5uphyybpnc784beat.png" alt="Plotting with block elements"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And maybe we should change the distribution a bit to really appreciate the extra resolution this has bought us. We can take the square root of each random number, and increase the sample count to 10,000:&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="p"&gt;...&lt;/span&gt;

&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;math.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="cp"&gt;#define SAMPLE_COUNT 10000
&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="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SAMPLE_COUNT&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;size_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;SAMPLE_COUNT&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="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;data&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="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqrtf&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;RAND_MAX&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="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;Using &lt;code&gt;sqrtf&lt;/code&gt; (square root for floats) from &lt;code&gt;math.h&lt;/code&gt; we're getting a more interesting distribution:&lt;/p&gt;

&lt;p&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%2F3e9aol0pxrdq4m8ykpc7.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%2F3e9aol0pxrdq4m8ykpc7.png" alt="Square root distribution"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A plot like this would have never been possible with spaces and pound signs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Autoscaling the X-axis
&lt;/h2&gt;

&lt;p&gt;We're almost done, but there still is one issue: If our random floats go outside the 0.0 - 1.0 range, we have a problem.&lt;/p&gt;

&lt;p&gt;Let's go back to a uniform distribution, but subtract 0.5 to center the numbers around 0.0:&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="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SAMPLE_COUNT&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;size_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;SAMPLE_COUNT&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="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;data&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="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;RAND_MAX&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="mi"&gt;5&lt;/span&gt;&lt;span class="n"&gt;f&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;That results in the following abomination:&lt;/p&gt;

&lt;p&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%2F5ogbhirc6wlrlrbdbyrs.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%2F5ogbhirc6wlrlrbdbyrs.png" alt="Not scaling the X-axis"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We could either manually specify the range we want to plot our histogram at, or let it auto-scale the x-axis as well. I prefer the latter. This allows us to just throw anything at it, and the plot function will just figure it out.&lt;/p&gt;

&lt;p&gt;So in order to do this, we need to keep track of the x-range (the minimum and maximum value of our samples):&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="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;x_min&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&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="n"&gt;x_max&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&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;for&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;i&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;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;SAMPLE_COUNT&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;x_min&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;x_min&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;val&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;val&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x_max&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;x_max&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;val&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="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;x_range&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x_max&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;x_min&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have &lt;code&gt;x_min&lt;/code&gt;, &lt;code&gt;x_max&lt;/code&gt; and &lt;code&gt;x_range&lt;/code&gt;. And we're going to do some basic math to scale and shift the samples back into a 0.0 - 1.0 range, after which we can multiply them with the number of columns &lt;code&gt;COLS&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;First we calculate the x-scale. And we guard against a range of 0.0 to avoid dividing by zero:&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="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;x_scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x_range&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;COLS&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;x_range&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="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this, we can shift and scale each sample, before calculating which bucket it goes into:&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="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;buckets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;COLS&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="k"&gt;for&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;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;len&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;bucket_ix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&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="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;x_min&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x_scale&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;bucket_ix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bucket_ix&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;COLS&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;COLS&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;bucket_ix&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;buckets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;bucket_ix&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Subtracting &lt;code&gt;x_min&lt;/code&gt; makes sure we shift the entire range to start from 0.0. Then multiplying by &lt;code&gt;x_scale&lt;/code&gt; scales it up to our number of columns.&lt;/p&gt;

&lt;p&gt;After this, we make sure we don't exceed &lt;code&gt;COLS - 1&lt;/code&gt; which would mean we access elements outside of our &lt;code&gt;buckets&lt;/code&gt; array.&lt;/p&gt;

&lt;p&gt;This gets us back to a properly scaled histogram of our uniform distribution:&lt;/p&gt;

&lt;p&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%2Fvza1vmltkj8aijhlrh29.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%2Fvza1vmltkj8aijhlrh29.png" alt="Autoscaling the X-axis"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Splitting the code into a library
&lt;/h2&gt;

&lt;p&gt;Up until this point we've been cluttering up our &lt;code&gt;main&lt;/code&gt; function. I'd like to clean it up and end up with something like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;main.c&lt;/strong&gt;&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;"plt/plt.h"&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;
#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="cp"&gt;#define SAMPLE_COUNT 10000
#define ROWS 16
#define COLS 72
&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="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SAMPLE_COUNT&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;size_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;SAMPLE_COUNT&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;roll_a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;RAND_MAX&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;roll_b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;RAND_MAX&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;data&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="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;roll_a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;roll_b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;plt_hist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SAMPLE_COUNT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ROWS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;COLS&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;A lot cleaner. Our plot functionality is now just one &lt;code&gt;plt/plt.h&lt;/code&gt; include, and one &lt;code&gt;plt_hist()&lt;/code&gt; call.&lt;/p&gt;

&lt;p&gt;Note that we also do two random rolls, and add them together. This gives quite an interesting distribution:&lt;/p&gt;

&lt;p&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%2Flx08fy93tqwjw0tuq76o.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%2Flx08fy93tqwjw0tuq76o.png" alt="Two random numbers added"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And our &lt;code&gt;plt&lt;/code&gt; library looks like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;plt/plt.h&lt;/strong&gt;&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;#ifndef _PLT_H
#define _PLT_H
&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="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;plt_hist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;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;len&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;rows&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;cols&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cp"&gt;#endif // _PLT_H
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;plt/plt.c&lt;/strong&gt;&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;"plt.h"&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;
#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="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;plt_hist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;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;len&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;rows&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;cols&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Get the x range&lt;/span&gt;
  &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;x_min&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&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="n"&gt;x_max&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&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;for&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;i&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;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;len&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;x_min&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;x_min&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;val&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;val&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x_max&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;x_max&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;val&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="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;x_range&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x_max&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;x_min&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;x_scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x_range&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;cols&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;x_range&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="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Keep track of bucket counts&lt;/span&gt;
  &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;buckets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cols&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="k"&gt;for&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;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;len&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;bucket_ix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&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="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;x_min&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x_scale&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;bucket_ix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bucket_ix&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cols&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;cols&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;bucket_ix&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;buckets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;bucket_ix&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="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Find the max count&lt;/span&gt;
  &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;bucket_max&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="k"&gt;for&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;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;cols&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="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;buckets&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="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bucket_max&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;bucket_max&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;buckets&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="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// clang-format off&lt;/span&gt;
  &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;blocks&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="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"\u2581"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"\u2582"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"\u2583"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"\u2584"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"\u2585"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"\u2586"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"\u2587"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"\u2588"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="c1"&gt;// clang-format on&lt;/span&gt;
  &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;block_count&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="n"&gt;blocks&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="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;blocks&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="c1"&gt;// Scale heights&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;size_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;cols&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="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;buckets&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="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buckets&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="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;block_count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;bucket_max&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Plotting&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;size_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;rows&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&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;block_count&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;size_t&lt;/span&gt; &lt;span class="n"&gt;j&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;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;cols&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;j&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="n"&gt;block_ix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;buckets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;block_ix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;block_ix&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;block_ix&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;block_ix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;block_ix&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;block_count&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;block_count&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;block_ix&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;"%s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;blocks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;block_ix&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;"&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="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;That's it! Thanks for reading.&lt;/p&gt;

&lt;p&gt;I'm maintaining it on github as &lt;a href="https://github.com/vanderoost/plt.c" rel="noopener noreferrer"&gt;plt.c&lt;/a&gt; so feel free to grab it from there.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://vanderoost.com/articles/2026/09/11/histogram-plotting-in-the-terminal/" rel="noopener noreferrer"&gt;vanderoost.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://vanderoost.com/articles/2026/08/05/levels-of-effective-makefile-cheatsheet/" rel="noopener noreferrer"&gt;The 7 levels of highly effective Makefiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/vanderoost/plt.c" rel="noopener noreferrer"&gt;plt.c on Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>coding</category>
      <category>github</category>
      <category>opensource</category>
      <category>programming</category>
    </item>
    <item>
      <title>The 7 levels of highly effective Makefiles</title>
      <dc:creator>Richard</dc:creator>
      <pubDate>Sun, 20 Sep 2026 13:26:13 +0000</pubDate>
      <link>https://dev.to/vanderoost/the-7-levels-of-highly-effective-makefiles-758</link>
      <guid>https://dev.to/vanderoost/the-7-levels-of-highly-effective-makefiles-758</guid>
      <description>&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/PPDyWuWz9VE" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Rumor has it that all Makefiles in use today were written in a time when dinosaurs roamed the earth. Nobody &lt;em&gt;actually&lt;/em&gt; writes new Makefiles anymore, right?&lt;/p&gt;

&lt;p&gt;Right. Makefiles cause a lot of anxiety, but in this article, I will walk you through the humbling experience of writing a Makefile from scratch. To automate a C build system.&lt;/p&gt;

&lt;p&gt;If you don't know what I'm talking about, Make is a tool for &lt;em&gt;making files&lt;/em&gt; based on certain &lt;em&gt;rules&lt;/em&gt;. It can be abused to do more, and to automate other terminal shenanigans. Think of running your tests, deploying, building Docker images, etc.&lt;/p&gt;

&lt;p&gt;Once you find yourself running certain commands repeatedly in a codebase, your first instinct might be to stash them away in some bash script.&lt;/p&gt;

&lt;p&gt;This works, but Makefiles give you some extra tech: &lt;code&gt;make&lt;/code&gt; automatically creates a dependency graph of all the files you want to "make", and then uses the last modification timestamps of each file to determine what actually has to be made.&lt;/p&gt;

&lt;p&gt;So it's more efficient, and it has some other cool tricks that we'll dive into.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; (spoiler alert): this is the final Makefile we'll end up with:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;CFLAGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-Wall&lt;/span&gt; &lt;span class="nt"&gt;-Wextra&lt;/span&gt;

&lt;span class="nv"&gt;NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; main
&lt;span class="nv"&gt;BIN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; bin
&lt;span class="nv"&gt;OBJ&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; obj
&lt;span class="nv"&gt;SRC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; src

&lt;span class="nv"&gt;EXEC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;BIN&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="p"&gt;$(&lt;/span&gt;NAME&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;BIN_SRCS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;wildcard &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.c&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;LIB_SRCS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;wildcard &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.c&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;ALL_SRCS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;BIN_SRCS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;LIB_SRCS&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;BINS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;patsubst &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/%.c,&lt;span class="p"&gt;$(&lt;/span&gt;BIN&lt;span class="p"&gt;)&lt;/span&gt;/%,&lt;span class="p"&gt;$(&lt;/span&gt;BIN_SRCS&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nv"&gt;OBJS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;patsubst &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/%.c,&lt;span class="p"&gt;$(&lt;/span&gt;OBJ&lt;span class="p"&gt;)&lt;/span&gt;/%.o,&lt;span class="p"&gt;$(&lt;/span&gt;LIB_SRCS&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nv"&gt;DEPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;patsubst &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/%.c,&lt;span class="p"&gt;$(&lt;/span&gt;OBJ&lt;span class="p"&gt;)&lt;/span&gt;/%.d,&lt;span class="p"&gt;$(&lt;/span&gt;ALL_SRCS&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="nl"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(BINS)&lt;/span&gt;

&lt;span class="nl"&gt;$(BINS)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(BIN)/%: $(OBJ)/%.o $(OBJS)&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;@D&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;CC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;LDFLAGS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$^&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;LDLIBS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt;

&lt;span class="nl"&gt;$(OBJ)/%.o&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(SRC)/%.c&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;@D&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;CC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;CFLAGS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-MMD&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nv"&gt;$&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt;

&lt;span class="nl"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(EXEC)&lt;/span&gt;
    &lt;span class="nv"&gt;$&amp;lt;&lt;/span&gt;

&lt;span class="nl"&gt;watch&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    find &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-type&lt;/span&gt; f | entr &lt;span class="nt"&gt;-c&lt;/span&gt; make run

&lt;span class="nl"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;RM&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;BIN&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;OBJ&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;-include&lt;/span&gt;&lt;span class="sx"&gt; $(DEPS)&lt;/span&gt;

&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;all run watch clean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If this looks a bit intimidating, not to worry. We'll start from zero with only a &lt;code&gt;main.c&lt;/code&gt; file and build it up step by step, to multiple &lt;code&gt;.c&lt;/code&gt; and &lt;code&gt;.h&lt;/code&gt; files in a proper project setup with subdirectories. I use this post myself as a Makefile cheatsheet.&lt;/p&gt;

&lt;p&gt;All the code can also be found in my &lt;a href="https://github.com/vanderoost/c-makefile-template" rel="noopener noreferrer"&gt;C Makefile template&lt;/a&gt; repo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Level 0 - Nothing
&lt;/h2&gt;

&lt;p&gt;Literally no Makefile at all, so this one doesn't count. But even without a Makefile, we can already start using &lt;code&gt;make&lt;/code&gt; because it has a bunch of default rules.&lt;/p&gt;

&lt;p&gt;So without a Makefile, our project directory contains only a single file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;└── main.c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before we knew about &lt;code&gt;make&lt;/code&gt;, we would compile it into a &lt;code&gt;main&lt;/code&gt; executable like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% cc main.c -o main
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But with &lt;code&gt;make&lt;/code&gt;, we can simply run &lt;code&gt;make main&lt;/code&gt; to do the same:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% make main
cc     main.c   -o main
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That output on the last line shows the command that &lt;code&gt;make&lt;/code&gt; runs for us.&lt;/p&gt;

&lt;p&gt;It compiles &lt;code&gt;main.c&lt;/code&gt; into an executable called &lt;code&gt;main&lt;/code&gt; which we can run to verify it's all working:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% ./main
hello world
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that works, but how did &lt;code&gt;make&lt;/code&gt; know what to do without a Makefile?&lt;/p&gt;

&lt;p&gt;There are some default pattern matching rules, and &lt;code&gt;make&lt;/code&gt; magically figures it out.&lt;/p&gt;

&lt;p&gt;You don't need to understand this right now, but the rule that applies here looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;%&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;%.c&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;LINK.c&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$^&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;LOADLIBES&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;LDLIBS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;%&lt;/code&gt; picks up the target we want to make, &lt;code&gt;main&lt;/code&gt; in this case. The &lt;code&gt;%.c&lt;/code&gt; means it has a prerequisite of &lt;code&gt;main.c&lt;/code&gt; where the &lt;code&gt;%&lt;/code&gt; is the pattern. We happen to have a &lt;code&gt;main.c&lt;/code&gt;, which is why this works. Then the actual "recipe" for making it is a bunch of variables that end up running &lt;code&gt;cc     main.c   -o main&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can see all the implicit rules and default variables with &lt;code&gt;make -p&lt;/code&gt; if you're curious.&lt;/p&gt;

&lt;p&gt;If your file is called &lt;code&gt;program.c&lt;/code&gt; instead, you can run &lt;code&gt;make program&lt;/code&gt;, and it spits out the file &lt;code&gt;program&lt;/code&gt; as the executable.&lt;/p&gt;

&lt;p&gt;Making without a Makefile is a bit of a party trick, but would I ever use this in practice? Actually, yes. Every time I quickly write a &lt;code&gt;main.c&lt;/code&gt; to test something, all I have to do is type &lt;code&gt;make main&lt;/code&gt; and it's compiled.&lt;/p&gt;

&lt;p&gt;What if you want to change the compiler, or add flags? No problem. The default behavior of &lt;code&gt;make&lt;/code&gt; is to compile with whatever is set in the &lt;code&gt;CC&lt;/code&gt; environment variable, and it uses the flags from &lt;code&gt;CFLAGS&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So if you want to compile with &lt;code&gt;gcc&lt;/code&gt; instead of &lt;code&gt;cc&lt;/code&gt;, you can run it like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% CC=gcc make main
gcc     main.c   -o main
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adding flags can be done with the &lt;code&gt;CFLAGS&lt;/code&gt; variable:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% CC=gcc CFLAGS="-Wall -Wextra" make main
gcc -Wall -Wextra    main.c   -o main
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But at this point it's easier to just use a Makefile. So let's check out the next level.&lt;/p&gt;

&lt;h2&gt;
  
  
  Level 1 - Bare minimum
&lt;/h2&gt;

&lt;p&gt;Now we actually write a Makefile, the configuration for &lt;code&gt;make&lt;/code&gt;. For our "bare minimum" level I want to add three features:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Automatically run after compiling&lt;/li&gt;
&lt;li&gt;Configure compile flags&lt;/li&gt;
&lt;li&gt;Cleanup to get back to the initial state&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The filename is just Makefile so our project directory looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── Makefile
└── main.c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A filename of &lt;code&gt;makefile&lt;/code&gt; also works, but Makefile is the convention I'm sticking to.&lt;/p&gt;

&lt;p&gt;A Makefile mainly consists of a bunch of &lt;em&gt;rules&lt;/em&gt;. This is what a rule looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;target&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;prerequisites&lt;/span&gt;
    recipe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we have a &lt;code&gt;target&lt;/code&gt; that's typically a file, like &lt;code&gt;main&lt;/code&gt;. It can have prerequisites which are typically other files, but can also be other non-file targets. And finally the &lt;code&gt;recipe&lt;/code&gt; which is the command to build the &lt;code&gt;target&lt;/code&gt;, like a &lt;code&gt;cc&lt;/code&gt; compile command.&lt;/p&gt;

&lt;p&gt;One thing to watch out for: that indentation before the recipe has to be a literal tab character. Spaces will get you &lt;code&gt;Makefile:2: *** missing separator.  Stop.&lt;/code&gt;, which is the most common way to break a fresh Makefile.&lt;/p&gt;

&lt;p&gt;To automatically run our program, feature 1, I'm going to add a target called &lt;code&gt;run&lt;/code&gt;, with a prerequisite &lt;code&gt;main&lt;/code&gt; because we need the main executable to run it. And the action of running it is just calling &lt;code&gt;./main&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;
    ./main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can run &lt;code&gt;make run&lt;/code&gt;, and this is what happens:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% make run
cc     main.c   -o main
./main
hello world
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First it gets compiled, then it runs &lt;code&gt;./main&lt;/code&gt;. How does &lt;code&gt;make&lt;/code&gt; know that it needs to compile? Because we said that &lt;code&gt;main&lt;/code&gt; is a prerequisite of &lt;code&gt;run&lt;/code&gt; (i.e. &lt;code&gt;run&lt;/code&gt; depends on &lt;code&gt;main&lt;/code&gt;). So it will try to &lt;code&gt;make main&lt;/code&gt; first, before running it. And since &lt;code&gt;make main&lt;/code&gt; already worked without a Makefile, this still works.&lt;/p&gt;

&lt;p&gt;But even better, when we run it a second time:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% make run
./main
hello world
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it only runs &lt;code&gt;main&lt;/code&gt;, without compiling. Why? Because &lt;code&gt;make&lt;/code&gt; is smart enough to look at the prerequisites of our &lt;code&gt;run&lt;/code&gt; target, &lt;code&gt;main&lt;/code&gt;. And since it already exists, it's not going to "make" it again.&lt;/p&gt;

&lt;p&gt;We know that the targets in a Makefile are usually files, but &lt;code&gt;run&lt;/code&gt; is not supposed to be a file. What if there is a file in our project directory that's literally called &lt;code&gt;run&lt;/code&gt;? Let's see what happens:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% make main
cc     main.c   -o main
% touch run
% make run
make: `run' is up to date.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now &lt;code&gt;make run&lt;/code&gt; doesn't do anything, because the target &lt;code&gt;run&lt;/code&gt; is "up to date". That happens because the target file &lt;code&gt;run&lt;/code&gt; is newer than the prerequisite file &lt;code&gt;main&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To tell make that our &lt;code&gt;run&lt;/code&gt; target is not really referencing a file, we can mark it with &lt;code&gt;.PHONY&lt;/code&gt; like so:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;
    ./main

&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now &lt;code&gt;make run&lt;/code&gt; works again, regardless of our accidental &lt;code&gt;run&lt;/code&gt; file:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% make run
./main
hello world
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even though we'll probably never have a &lt;code&gt;run&lt;/code&gt; file in the root of our project directory, it's good practice to mark all the non-file targets with &lt;code&gt;.PHONY&lt;/code&gt; to clarify intent.&lt;/p&gt;

&lt;p&gt;Feature 2 is adding custom compiler flags, easy:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;CFLAGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-Wall&lt;/span&gt; &lt;span class="nt"&gt;-Wextra&lt;/span&gt;

&lt;span class="nl"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;
    ./main

&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's all. Because we're using the default rule to make &lt;code&gt;main&lt;/code&gt;, the flags will be picked up automatically:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% make main
cc -Wall -Wextra    main.c   -o main
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Feature 3 is adding a cleanup shortcut to undo everything. I'll call it &lt;code&gt;clean&lt;/code&gt; and you see this in 9 out of 10 Makefiles, so we're just sticking to the convention. This target is, like &lt;code&gt;run&lt;/code&gt;, not supposed to be a file, so we mark it as &lt;code&gt;.PHONY&lt;/code&gt;, and all I want it to do is remove our &lt;code&gt;main&lt;/code&gt; executable:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;CFLAGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-Wall&lt;/span&gt; &lt;span class="nt"&gt;-Wextra&lt;/span&gt;

&lt;span class="nl"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;
    ./main

&lt;span class="nl"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;rm &lt;/span&gt;main

&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;run clean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the target is &lt;code&gt;clean&lt;/code&gt;, it has no prerequisites, and all it does is run &lt;code&gt;rm main&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% make clean
rm main
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But what if we run &lt;code&gt;make clean&lt;/code&gt; and &lt;code&gt;main&lt;/code&gt; doesn't exist?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% make clean
rm main
rm: main: No such file or directory
make: *** [clean] Error 1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's an error. It doesn't really matter, but for good measure we can change the recipe to &lt;code&gt;rm -f main&lt;/code&gt; or use the &lt;code&gt;$(RM)&lt;/code&gt; variable that &lt;code&gt;make&lt;/code&gt; has for us:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;CFLAGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-Wall&lt;/span&gt; &lt;span class="nt"&gt;-Wextra&lt;/span&gt;

&lt;span class="nl"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;
    ./main

&lt;span class="nl"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;RM&lt;span class="p"&gt;)&lt;/span&gt; main

&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;run clean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now &lt;code&gt;make clean&lt;/code&gt; runs without errors, even if there is nothing to clean:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% make clean
rm -f main
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before we go to the next level, I want to add one finishing touch here to change the behavior of running just &lt;code&gt;make&lt;/code&gt; without anything else.&lt;/p&gt;

&lt;p&gt;When you have a Makefile, running &lt;code&gt;make&lt;/code&gt; will run the first rule specified in the file, which is &lt;code&gt;run&lt;/code&gt; in our case.&lt;/p&gt;

&lt;p&gt;That's a bit confusing. I want to run the program with &lt;code&gt;make run&lt;/code&gt;, but when I type &lt;code&gt;make&lt;/code&gt;, it makes more sense to only compile (make) it, without running it.&lt;/p&gt;

&lt;p&gt;A common pattern to achieve this is using an &lt;code&gt;all&lt;/code&gt; target at the top of the Makefile:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;CFLAGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-Wall&lt;/span&gt; &lt;span class="nt"&gt;-Wextra&lt;/span&gt;

&lt;span class="nl"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;

&lt;span class="nl"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;
    ./main

&lt;span class="nl"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;RM&lt;span class="p"&gt;)&lt;/span&gt; main

&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;all run clean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We give it a prerequisite of &lt;code&gt;main&lt;/code&gt; just like we did for &lt;code&gt;run&lt;/code&gt;, so running it will make sure that &lt;code&gt;main.c&lt;/code&gt; is compiled into &lt;code&gt;main&lt;/code&gt;. But then the recipe is empty, so it doesn't do anything else:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% make
cc -Wall -Wextra    main.c   -o main
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It just "makes" our program, which is the most intuitive thing to do after typing &lt;code&gt;make&lt;/code&gt; (or &lt;code&gt;make all&lt;/code&gt;). And again, &lt;code&gt;all&lt;/code&gt; is not referring to a file, so it's added to the &lt;code&gt;.PHONY&lt;/code&gt; list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Level 2 - Immediate feedback
&lt;/h2&gt;

&lt;p&gt;For me, programming is more productive and fun with a tight feedback loop. So when I make an edit, I want it to instantly compile and run (or crash).&lt;/p&gt;

&lt;p&gt;To do this, we can use a "file watcher" utility. I always use &lt;a href="https://github.com/eradman/entr" rel="noopener noreferrer"&gt;&lt;code&gt;entr&lt;/code&gt;&lt;/a&gt; for this, and set it up as a new rule in the Makefile.&lt;/p&gt;

&lt;p&gt;So let's add a &lt;code&gt;watch&lt;/code&gt; rule to the Makefile, because it "watches" our source files for changes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;CFLAGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-Wall&lt;/span&gt; &lt;span class="nt"&gt;-Wextra&lt;/span&gt;

&lt;span class="nl"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;

&lt;span class="nl"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;
    ./main

&lt;span class="nl"&gt;watch&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.c | entr make run

&lt;span class="nl"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;RM&lt;span class="p"&gt;)&lt;/span&gt; main

&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;all run watch clean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is what happens when we run &lt;code&gt;make watch&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% make watch
ls *.c | entr make run
cc -Wall -Wextra    main.c   -o main
./main
hello world
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first part, &lt;code&gt;ls *.c&lt;/code&gt; just lists out all &lt;code&gt;.c&lt;/code&gt; files in our project directory. All we have is &lt;code&gt;main.c&lt;/code&gt; for now.&lt;/p&gt;

&lt;p&gt;Then it pipes that list of files to &lt;code&gt;entr&lt;/code&gt;, which starts watching the file names that got passed in. When a file changes, it runs the command &lt;code&gt;make run&lt;/code&gt; which compiles and runs our &lt;code&gt;main&lt;/code&gt; executable.&lt;/p&gt;

&lt;p&gt;After running &lt;code&gt;make watch&lt;/code&gt;, it stays "active", waiting for changes. So if we edit &lt;code&gt;main.c&lt;/code&gt; and add some punctuation, we instantly see this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% make watch
ls *.c | entr make run
cc -Wall -Wextra    main.c   -o main
./main
hello world
cc -Wall -Wextra    main.c   -o main
./main
Hello, world!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which is super useful. One thing I usually like to pass to &lt;code&gt;entr&lt;/code&gt; is the &lt;code&gt;-c&lt;/code&gt; flag which clears the screen before it updates:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;CFLAGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-Wall&lt;/span&gt; &lt;span class="nt"&gt;-Wextra&lt;/span&gt;

&lt;span class="nl"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;

&lt;span class="nl"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;
    ./main

&lt;span class="nl"&gt;watch&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.c | entr &lt;span class="nt"&gt;-c&lt;/span&gt; make run

&lt;span class="nl"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;RM&lt;span class="p"&gt;)&lt;/span&gt; main

&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;all run watch clean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prevents the terminal from cluttering up too much.&lt;/p&gt;

&lt;p&gt;Now, whenever we mess up, there is instant feedback. Like a subtle slap on the wrist that instantly catches errors and bugs.&lt;/p&gt;

&lt;p&gt;It also allows for faster experimentation: just try something, hit save, and the instant compile + run shows you the result.&lt;/p&gt;

&lt;p&gt;Also good to know when using &lt;code&gt;entr&lt;/code&gt;: Hitting Space re-runs the command. Hitting Q will quit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Level 3 - Compiling multiple files
&lt;/h2&gt;

&lt;p&gt;So far we've just been using &lt;code&gt;main.c&lt;/code&gt; as our source file. This is great for quick tools or testing some new concept. But most projects are organized across multiple files.&lt;/p&gt;

&lt;p&gt;Let's say I want to implement some tools for generating random numbers. I have an &lt;code&gt;rng.h&lt;/code&gt; header file, and an implementation in &lt;code&gt;rng.c&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To keep it simple, I'm still storing everything in the root of our project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── Makefile
├── main.c
├── rng.c
└── rng.h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our &lt;code&gt;main.c&lt;/code&gt; file now has an &lt;code&gt;#include "rng.h"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We could compile this by hand like so:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% cc main.c rng.c -o main
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Integrating this into the Makefile looks like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;CFLAGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-Wall&lt;/span&gt; &lt;span class="nt"&gt;-Wextra&lt;/span&gt;

&lt;span class="nl"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;

&lt;span class="nl"&gt;main&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;main.c rng.c&lt;/span&gt;

&lt;span class="nl"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;
    ./main

&lt;span class="nl"&gt;watch&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.c | entr &lt;span class="nt"&gt;-c&lt;/span&gt; make run

&lt;span class="nl"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;RM&lt;span class="p"&gt;)&lt;/span&gt; main

&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;all run watch clean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All we did was specify our target &lt;code&gt;main&lt;/code&gt; and give it the prerequisites &lt;code&gt;main.c&lt;/code&gt; and &lt;code&gt;rng.c&lt;/code&gt;. We don't give it a recipe, because we can still rely on the implicit recipe that &lt;code&gt;make&lt;/code&gt; comes with by default. So this now works:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% make run
cc -Wall -Wextra    main.c rng.c   -o main
./main
random float: 0.633477
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But there is a way to simplify this even more. We don't need to write out the &lt;code&gt;main.c&lt;/code&gt; prerequisite, because that's also implied by &lt;code&gt;make&lt;/code&gt; already. So the more compact version of the rule looks like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;CFLAGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-Wall&lt;/span&gt; &lt;span class="nt"&gt;-Wextra&lt;/span&gt;

&lt;span class="nl"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;

&lt;span class="nl"&gt;main&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;rng.c&lt;/span&gt;

&lt;span class="nl"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;
    ./main

&lt;span class="nl"&gt;watch&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.c | entr &lt;span class="nt"&gt;-c&lt;/span&gt; make run

&lt;span class="nl"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;RM&lt;span class="p"&gt;)&lt;/span&gt; main

&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;all run watch clean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And everything still works:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% make run
cc -Wall -Wextra    main.c rng.c   -o main
./main
random float: 0.503928
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Level 4 - Source directory
&lt;/h2&gt;

&lt;p&gt;Let's take the first step into organizing our project a bit more, by moving our source code into a &lt;code&gt;src&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── Makefile
└── src
    ├── main.c
    ├── rng.c
    └── rng.h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That breaks our build, because &lt;code&gt;make&lt;/code&gt; can't find our source files anymore:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% make run
make: *** No rule to make target `rng.c', needed by `main'.  Stop.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fixing this in our Makefile is surprisingly simple. We just have to tell it about the new &lt;code&gt;src&lt;/code&gt; directory by adding it to the &lt;code&gt;VPATH&lt;/code&gt; variable:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;CFLAGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-Wall&lt;/span&gt; &lt;span class="nt"&gt;-Wextra&lt;/span&gt;

&lt;span class="nv"&gt;VPATH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; src

&lt;span class="nl"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;

&lt;span class="nl"&gt;main&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;rng.c&lt;/span&gt;

&lt;span class="nl"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;
    ./main

&lt;span class="nl"&gt;watch&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;ls &lt;/span&gt;src/&lt;span class="k"&gt;*&lt;/span&gt;.c | entr &lt;span class="nt"&gt;-c&lt;/span&gt; make run

&lt;span class="nl"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;RM&lt;span class="p"&gt;)&lt;/span&gt; main

&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;all run watch clean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On line 13 we're also fixing our &lt;code&gt;watch&lt;/code&gt; rule and letting it know about the new &lt;code&gt;src&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;And that fixes the build:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% make run
cc -Wall -Wextra    src/main.c src/rng.c   -o main
./main
random float: 0.621248
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're starting to see a bit of repetition in our Makefile, so let's take a moment to add some variables to DRY things up:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;CFLAGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-Wall&lt;/span&gt; &lt;span class="nt"&gt;-Wextra&lt;/span&gt;

&lt;span class="nv"&gt;EXEC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; main
&lt;span class="nv"&gt;SRC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; src

&lt;span class="nv"&gt;VPATH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nl"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(EXEC)&lt;/span&gt;

&lt;span class="nl"&gt;$(EXEC)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;rng.c&lt;/span&gt;

&lt;span class="nl"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(EXEC)&lt;/span&gt;
    ./&lt;span class="p"&gt;$(&lt;/span&gt;EXEC&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nl"&gt;watch&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.c | entr &lt;span class="nt"&gt;-c&lt;/span&gt; make run

&lt;span class="nl"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;RM&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;EXEC&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;all run watch clean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have an &lt;code&gt;EXEC&lt;/code&gt; variable for our final executable. If we ever need to change this name, we can do it in one place. Same for our source code directory, stored in &lt;code&gt;SRC&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We've already seen the syntax for referencing a &lt;code&gt;make&lt;/code&gt; variable before when we used &lt;code&gt;$(RM)&lt;/code&gt;, and we use it to reference &lt;code&gt;EXEC&lt;/code&gt; and &lt;code&gt;SRC&lt;/code&gt; as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Level 5 - Separate compilation
&lt;/h2&gt;

&lt;p&gt;Right now we're taking all our &lt;code&gt;.c&lt;/code&gt; source files, and compiling them in a single command. For this toy example that's totally fine and probably the fastest way, but for larger projects it could make sense to split this into multiple steps.&lt;/p&gt;

&lt;p&gt;This way, when you make an edit to one source file, you only have to recompile that source file, and then link all compiled object files together, instead of compiling all source files on every edit.&lt;/p&gt;

&lt;p&gt;There's a second payoff too: because every &lt;code&gt;.o&lt;/code&gt; file becomes an independent target with no dependencies on the others, &lt;code&gt;make -j&lt;/code&gt; can compile them in parallel across multiple CPU cores.&lt;/p&gt;

&lt;p&gt;Manually, you can compile your &lt;code&gt;.c&lt;/code&gt; files into object &lt;code&gt;.o&lt;/code&gt; files, and then link them to get the final executable:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;cc main.c -c -o main.o
cc rng.c -c -o rng.o
cc main.o rng.o -o main
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's also possible to only compile the &lt;code&gt;rng&lt;/code&gt; library into an &lt;code&gt;.o&lt;/code&gt; file, and then link that in while compiling &lt;code&gt;main.c&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;cc rng.c -c -o rng.o
cc main.c rng.o -o main
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's see what that would look like in our Makefile. There is one super simple tweak we can make:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;CFLAGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-Wall&lt;/span&gt; &lt;span class="nt"&gt;-Wextra&lt;/span&gt;

&lt;span class="nv"&gt;EXEC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; main
&lt;span class="nv"&gt;SRC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; src

&lt;span class="nv"&gt;VPATH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nl"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(EXEC)&lt;/span&gt;

&lt;span class="nl"&gt;$(EXEC)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;rng.o&lt;/span&gt;

&lt;span class="nl"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(EXEC)&lt;/span&gt;
    ./&lt;span class="p"&gt;$(&lt;/span&gt;EXEC&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nl"&gt;watch&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.c | entr &lt;span class="nt"&gt;-c&lt;/span&gt; make run

&lt;span class="nl"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;RM&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;EXEC&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;all run watch clean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's almost too small to spot, but we've changed &lt;code&gt;rng.c&lt;/code&gt; to &lt;code&gt;rng.o&lt;/code&gt;. So we're telling &lt;code&gt;make&lt;/code&gt; our &lt;code&gt;main&lt;/code&gt; executable doesn't depend on &lt;code&gt;rng.c&lt;/code&gt; anymore, but &lt;code&gt;rng.o&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And &lt;code&gt;make&lt;/code&gt; happens to know how to compile &lt;code&gt;.c&lt;/code&gt; files into &lt;code&gt;.o&lt;/code&gt; files by using another standard pattern matching rule. So this works perfectly:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% make run
cc -Wall -Wextra   -c -o rng.o src/rng.c
cc -Wall -Wextra    src/main.c rng.o   -o main
./main
random float: 0.143407
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We went from a single &lt;code&gt;cc&lt;/code&gt; command to two. So if we now make an edit to &lt;code&gt;main.c&lt;/code&gt; to change the message, and run &lt;code&gt;make run&lt;/code&gt; again, it will skip compiling &lt;code&gt;rng.c&lt;/code&gt; because its &lt;code&gt;.o&lt;/code&gt; file is already up to date:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% make run
cc -Wall -Wextra    src/main.c rng.o   -o main
./main
the chance is: 0.226574
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a project with two &lt;code&gt;.c&lt;/code&gt; files and fewer than 20 lines of code, this sort of optimization is kind of silly over-engineering. But as the project grows it starts to make sense.&lt;/p&gt;

&lt;p&gt;You might have noticed that we have an &lt;code&gt;rng.o&lt;/code&gt; file sitting in our project directory now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── Makefile
├── main
├── rng.o
└── src
    ├── main.c
    ├── rng.c
    └── rng.h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows us to avoid recompiling the &lt;code&gt;rng&lt;/code&gt; library, but when we run &lt;code&gt;make clean&lt;/code&gt; we should clean it up:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;CFLAGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-Wall&lt;/span&gt; &lt;span class="nt"&gt;-Wextra&lt;/span&gt;

&lt;span class="nv"&gt;EXEC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; main
&lt;span class="nv"&gt;SRC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; src

&lt;span class="nv"&gt;VPATH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nl"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(EXEC)&lt;/span&gt;

&lt;span class="nl"&gt;$(EXEC)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;rng.o&lt;/span&gt;

&lt;span class="nl"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(EXEC)&lt;/span&gt;
    ./&lt;span class="p"&gt;$(&lt;/span&gt;EXEC&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nl"&gt;watch&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.c | entr &lt;span class="nt"&gt;-c&lt;/span&gt; make run

&lt;span class="nl"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;RM&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;EXEC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.o

&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;all run watch clean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we might add more than one library, we'll use &lt;code&gt;*.o&lt;/code&gt; to remove all object files on cleanup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Level 6 - Detect source files
&lt;/h2&gt;

&lt;p&gt;Our Makefile is in great shape, but one thing I don't like is that every time we decide to write a new library in our project, we have to also remember to edit the Makefile. Wouldn't it be great if &lt;code&gt;make&lt;/code&gt; could dynamically detect all source files?&lt;/p&gt;

&lt;p&gt;To make this work, we're going to use some new Makefile features like &lt;code&gt;wildcard&lt;/code&gt; and &lt;code&gt;patsubst&lt;/code&gt; to find files using pattern matching.&lt;/p&gt;

&lt;p&gt;We're also going to reorganize our source files one more time to make a better distinction between entrypoint &lt;code&gt;.c&lt;/code&gt; files and library &lt;code&gt;.c&lt;/code&gt; files.&lt;/p&gt;

&lt;p&gt;I've added a new sample library called &lt;code&gt;vec&lt;/code&gt;, to show how our build system can automatically detect multiple libraries.&lt;/p&gt;

&lt;p&gt;The new project structure looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── Makefile
└── src
    ├── main.c
    ├── rng
    │&amp;nbsp;&amp;nbsp; ├── rng.c
    │&amp;nbsp;&amp;nbsp; └── rng.h
    └── vec
        ├── vec.c
        └── vec.h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the convention is: Entrypoints that turn into an executable go directly under &lt;code&gt;src&lt;/code&gt;, and all libraries in a subdirectory of &lt;code&gt;src&lt;/code&gt;. By sticking to this rule, we can configure the Makefile to detect these files properly.&lt;/p&gt;

&lt;p&gt;We also have to change any &lt;code&gt;#include "rng.h"&lt;/code&gt; in our &lt;code&gt;main.c&lt;/code&gt; to &lt;code&gt;#include "rng/rng.h"&lt;/code&gt; after this reorganization.&lt;/p&gt;

&lt;p&gt;Our &lt;code&gt;.o&lt;/code&gt; files can be organized in their own dedicated directory &lt;code&gt;obj&lt;/code&gt; to reduce clutter in the root of the project.&lt;/p&gt;

&lt;p&gt;Our first step will be to detect all library source files based on a wildcard pattern. To do that, we use the &lt;code&gt;wildcard&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;LIBS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;wildcard &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.c&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function just expands all files that match the wildcard. So in our case, it will match &lt;code&gt;src/rng/rng.c&lt;/code&gt; and &lt;code&gt;src/vec/vec.c&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, we use the function &lt;code&gt;patsubst&lt;/code&gt; to derive file names of the &lt;code&gt;.o&lt;/code&gt; files we want to keep track of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;OBJ&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; obj
&lt;span class="nv"&gt;OBJS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;patsubst &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/%.c,&lt;span class="p"&gt;$(&lt;/span&gt;OBJ&lt;span class="p"&gt;)&lt;/span&gt;/%.o,&lt;span class="p"&gt;$(&lt;/span&gt;LIBS&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This one is a bit more complicated: It takes three parameters. The first one is the pattern to match, the second one is the new pattern to turn it into, and the third is a list of paths to do this with.&lt;/p&gt;

&lt;p&gt;So &lt;code&gt;OBJS&lt;/code&gt; is created out of &lt;code&gt;LIBS&lt;/code&gt;, and transforms them like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/rng/rng.c -&amp;gt; obj/rng/rng.o
src/vec/vec.c -&amp;gt; obj/vec/vec.o
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we're going to use &lt;code&gt;OBJS&lt;/code&gt; as the prerequisites of our &lt;code&gt;EXEC&lt;/code&gt; target:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;$(EXEC)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(OBJS)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of listing the &lt;code&gt;.o&lt;/code&gt; files of each library manually, we now have the &lt;code&gt;$(OBJS)&lt;/code&gt; variable that dynamically updates.&lt;/p&gt;

&lt;p&gt;This is what the second rule looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;$(OBJ)/%.o&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(SRC)/%.c&lt;/span&gt;
    &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;@D&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;CC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;CFLAGS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nv"&gt;$&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's a lot more going on. The target is dynamic due to the &lt;code&gt;%&lt;/code&gt;, so it matches all &lt;code&gt;.o&lt;/code&gt; files in the &lt;code&gt;obj&lt;/code&gt; directory and dynamically creates a corresponding &lt;code&gt;.c&lt;/code&gt; prerequisite for each one in the &lt;code&gt;src&lt;/code&gt; directory. So &lt;code&gt;obj/rng/rng.o&lt;/code&gt; will match with &lt;code&gt;src/rng/rng.c&lt;/code&gt; for example.&lt;/p&gt;

&lt;p&gt;The recipe of this rule has two commands. The first one just ensures that the directory of the target exists. The variable &lt;code&gt;$(@D)&lt;/code&gt; magically references the directory of the target.&lt;/p&gt;

&lt;p&gt;The second command is just compiling the &lt;code&gt;.c&lt;/code&gt; file into the &lt;code&gt;.o&lt;/code&gt; file. Again, it uses two magic variables: &lt;code&gt;$&amp;lt;&lt;/code&gt; to match the first prerequisite, and &lt;code&gt;$@&lt;/code&gt; to match the target.&lt;/p&gt;

&lt;p&gt;Our &lt;code&gt;watch&lt;/code&gt; rule has to look for source files recursively in &lt;code&gt;src&lt;/code&gt;, so we can use &lt;code&gt;find&lt;/code&gt; for this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;watch&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    find &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-type&lt;/span&gt; f | entr &lt;span class="nt"&gt;-c&lt;/span&gt; make run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our &lt;code&gt;clean&lt;/code&gt; rule also has to be updated to match the new directory structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;RM&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;EXEC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;OBJ&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're removing the executable, and the entire &lt;code&gt;obj&lt;/code&gt; directory. Because we have the &lt;code&gt;mkdir -p&lt;/code&gt; recipe, we make sure we always rebuild these &lt;code&gt;obj&lt;/code&gt; directories when needed.&lt;/p&gt;

&lt;p&gt;If we add all of this to our Makefile, we get this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;CFLAGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-Wall&lt;/span&gt; &lt;span class="nt"&gt;-Wextra&lt;/span&gt;

&lt;span class="nv"&gt;EXEC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; main
&lt;span class="nv"&gt;SRC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; src
&lt;span class="nv"&gt;OBJ&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; obj

&lt;span class="nv"&gt;LIBS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;wildcard &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.c&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;OBJS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;patsubst &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/%.c,&lt;span class="p"&gt;$(&lt;/span&gt;OBJ&lt;span class="p"&gt;)&lt;/span&gt;/%.o,&lt;span class="p"&gt;$(&lt;/span&gt;LIBS&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="nv"&gt;VPATH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nl"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(EXEC)&lt;/span&gt;

&lt;span class="nl"&gt;$(EXEC)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(OBJS)&lt;/span&gt;

&lt;span class="nl"&gt;$(OBJ)/%.o&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(SRC)/%.c&lt;/span&gt;
    &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;@D&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;CC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;CFLAGS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nv"&gt;$&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt;

&lt;span class="nl"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(EXEC)&lt;/span&gt;
    ./&lt;span class="p"&gt;$(&lt;/span&gt;EXEC&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nl"&gt;watch&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    find &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-type&lt;/span&gt; f | entr &lt;span class="nt"&gt;-c&lt;/span&gt; make run

&lt;span class="nl"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;RM&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;EXEC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;OBJ&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;all run watch clean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we can run &lt;code&gt;make&lt;/code&gt; to see what happens:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% make
mkdir -p obj/rng
cc -Wall -Wextra -c src/rng/rng.c -o obj/rng/rng.o
mkdir -p obj/vec
cc -Wall -Wextra -c src/vec/vec.c -o obj/vec/vec.o
cc -Wall -Wextra    src/main.c obj/rng/rng.o obj/vec/vec.o   -o main
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it seems to work. First we make sure we have an &lt;code&gt;obj/rng&lt;/code&gt; directory. Then we're compiling &lt;code&gt;src/rng/rng.c&lt;/code&gt; into &lt;code&gt;obj/rng/rng.o&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We do the same thing for &lt;code&gt;obj/vec/vec.o&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And finally we compile &lt;code&gt;main.c&lt;/code&gt; and link &lt;code&gt;rng.o&lt;/code&gt; and &lt;code&gt;vec.o&lt;/code&gt; into the final executable &lt;code&gt;main&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After running &lt;code&gt;make&lt;/code&gt;, the project directory looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── Makefile
├── main
├── obj
│&amp;nbsp;&amp;nbsp; ├── rng
│&amp;nbsp;&amp;nbsp; │&amp;nbsp;&amp;nbsp; └── rng.o
│&amp;nbsp;&amp;nbsp; └── vec
│&amp;nbsp;&amp;nbsp;     └── vec.o
└── src
    ├── main.c
    ├── rng
    │&amp;nbsp;&amp;nbsp; ├── rng.c
    │&amp;nbsp;&amp;nbsp; └── rng.h
    └── vec
        ├── vec.c
        └── vec.h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So everything is working as expected.&lt;/p&gt;

&lt;p&gt;One thing I'd like to clean up is those &lt;code&gt;mkdir&lt;/code&gt; commands. I don't really want to see this in the &lt;code&gt;make&lt;/code&gt; output. We can prevent any recipe commands from being printed by prepending an &lt;code&gt;@&lt;/code&gt; like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;CFLAGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-Wall&lt;/span&gt; &lt;span class="nt"&gt;-Wextra&lt;/span&gt;

&lt;span class="nv"&gt;EXEC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; main
&lt;span class="nv"&gt;SRC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; src
&lt;span class="nv"&gt;OBJ&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; obj

&lt;span class="nv"&gt;LIBS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;wildcard &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.c&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;OBJS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;patsubst &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/%.c,&lt;span class="p"&gt;$(&lt;/span&gt;OBJ&lt;span class="p"&gt;)&lt;/span&gt;/%.o,&lt;span class="p"&gt;$(&lt;/span&gt;LIBS&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="nv"&gt;VPATH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nl"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(EXEC)&lt;/span&gt;

&lt;span class="nl"&gt;$(EXEC)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(OBJS)&lt;/span&gt;

&lt;span class="nl"&gt;$(OBJ)/%.o&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(SRC)/%.c&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;@D&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;CC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;CFLAGS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nv"&gt;$&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt;

&lt;span class="nl"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(EXEC)&lt;/span&gt;
    ./&lt;span class="p"&gt;$(&lt;/span&gt;EXEC&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nl"&gt;watch&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    find &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-type&lt;/span&gt; f | entr &lt;span class="nt"&gt;-c&lt;/span&gt; make run

&lt;span class="nl"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;RM&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;EXEC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;OBJ&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;all run watch clean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it looks a bit cleaner:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% make
cc -Wall -Wextra -c src/rng/rng.c -o obj/rng/rng.o
cc -Wall -Wextra -c src/vec/vec.c -o obj/vec/vec.o
cc -Wall -Wextra    src/main.c obj/rng/rng.o obj/vec/vec.o   -o main
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the great thing is: There is no trace of the word &lt;code&gt;rng&lt;/code&gt; or &lt;code&gt;vec&lt;/code&gt; anywhere in the Makefile, it's fully dynamic. So if we add more libraries later, they will be picked up and compiled automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Level 7 - Header dependencies
&lt;/h2&gt;

&lt;p&gt;There is one flaw in our current Makefile: When you edit a header (&lt;code&gt;.h&lt;/code&gt;) file, &lt;code&gt;make&lt;/code&gt; doesn't know it has to recompile that particular library.&lt;/p&gt;

&lt;p&gt;A simple way to test this is just updating the modification timestamp of one of the &lt;code&gt;.h&lt;/code&gt; files with &lt;code&gt;touch&lt;/code&gt; and running &lt;code&gt;make&lt;/code&gt; again:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% make
cc -Wall -Wextra -c src/rng/rng.c -o obj/rng/rng.o
cc -Wall -Wextra -c src/vec/vec.c -o obj/vec/vec.o
cc -Wall -Wextra    src/main.c obj/rng/rng.o obj/vec/vec.o   -o main
% touch src/rng/rng.h
% make
make: Nothing to be done for `all'.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It says "Nothing to be done", but we could have completely changed the header file.&lt;/p&gt;

&lt;p&gt;This is actually to be expected. We're not mentioning &lt;code&gt;.h&lt;/code&gt; files in the Makefile. All we do is say that the final executable depends on its corresponding &lt;code&gt;.c&lt;/code&gt; file, and all &lt;code&gt;.o&lt;/code&gt; files. Every &lt;code&gt;.o&lt;/code&gt; file only depends on its corresponding &lt;code&gt;.c&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Fortunately, compilers and &lt;code&gt;make&lt;/code&gt; can work together to fix this.&lt;/p&gt;

&lt;p&gt;When you compile, say, &lt;code&gt;main.c&lt;/code&gt; to &lt;code&gt;main.o&lt;/code&gt;, you can pass the &lt;code&gt;-MMD&lt;/code&gt; flag to let the compiler spit out not just the object file &lt;code&gt;main.o&lt;/code&gt; but also a dependency file &lt;code&gt;main.d&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% cc src/main.c -MMD -c
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It spits out two files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── Makefile
├── main.d
├── main.o
└── src
    ├── main.c
    ├── rng
    │&amp;nbsp;&amp;nbsp; ├── rng.c
    │&amp;nbsp;&amp;nbsp; └── rng.h
    └── vec
        ├── vec.c
        └── vec.h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that &lt;code&gt;main.d&lt;/code&gt; file is nothing complicated at all, it's just plain text:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;main.d&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;main.o&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;src/main.c src/rng/rng.h src/vec/vec.h&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This looks like a &lt;code&gt;make&lt;/code&gt; rule. And it specifies that &lt;code&gt;main.o&lt;/code&gt; depends on &lt;code&gt;src/main.c&lt;/code&gt; but also the two header files &lt;code&gt;src/rng/rng.h&lt;/code&gt; and &lt;code&gt;src/vec/vec.h&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The way the compiler "knows" this is by looking at the &lt;code&gt;main.c&lt;/code&gt; file, which specifies things like &lt;code&gt;#include "rng/rng.h"&lt;/code&gt; and &lt;code&gt;#include "vec/vec.h"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;-MMD&lt;/code&gt; flag actually has a few variations. Plain &lt;code&gt;-M&lt;/code&gt; prints the dependency list to stdout and doesn't compile anything. &lt;code&gt;-MD&lt;/code&gt; writes it to a &lt;code&gt;.d&lt;/code&gt; file &lt;em&gt;and&lt;/em&gt; compiles as usual. And &lt;code&gt;-MMD&lt;/code&gt; does the same as &lt;code&gt;-MD&lt;/code&gt;, but leaves out system headers. So that's the one we want, system headers are irrelevant in this case since we just want to know which files to recompile after we change one of our own header files.&lt;/p&gt;

&lt;p&gt;So now we want take those &lt;code&gt;.d&lt;/code&gt; files, and treat them like rules in our Makefile. And guess what, we can &lt;em&gt;include&lt;/em&gt; other files in our Makefile using the (you guessed it) &lt;code&gt;include&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I'd also like to make the final executable files a bit more flexible, allowing multiple final executables. And I want to store them in a subdirectory called &lt;code&gt;bin&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So this is the first thing I want to add:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; main
&lt;span class="nv"&gt;BIN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; bin
&lt;span class="nv"&gt;OBJ&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; obj
&lt;span class="nv"&gt;SRC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; src

&lt;span class="nv"&gt;EXEC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;BIN&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="p"&gt;$(&lt;/span&gt;NAME&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of specifying the &lt;code&gt;EXEC&lt;/code&gt; directly, we derive it from &lt;code&gt;$(BIN)&lt;/code&gt; and &lt;code&gt;$(NAME)&lt;/code&gt;. The &lt;code&gt;main&lt;/code&gt; executable will now be located at &lt;code&gt;bin/main&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Instead of only keeping track of the library &lt;code&gt;.c&lt;/code&gt; files, I want to keep track of the entrypoint &lt;code&gt;.c&lt;/code&gt; files as well in a variable:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;BIN_SRCS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;wildcard &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.c&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;LIB_SRCS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;wildcard &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.c&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now distinguish between the entrypoint source files with &lt;code&gt;$(BIN_SRCS)&lt;/code&gt;, and library source files with &lt;code&gt;$(LIB_SRCS)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now we have to modify the &lt;code&gt;patsubst&lt;/code&gt; line, and we'll add another one:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;BINS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;patsubst &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/%.c,&lt;span class="p"&gt;$(&lt;/span&gt;BIN&lt;span class="p"&gt;)&lt;/span&gt;/%,&lt;span class="p"&gt;$(&lt;/span&gt;BIN_SRCS&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nv"&gt;OBJS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;patsubst &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/%.c,&lt;span class="p"&gt;$(&lt;/span&gt;OBJ&lt;span class="p"&gt;)&lt;/span&gt;/%.o,&lt;span class="p"&gt;$(&lt;/span&gt;LIB_SRCS&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What's happening here with &lt;code&gt;BINS&lt;/code&gt; is pretty much: Take all &lt;code&gt;BIN_SRCS&lt;/code&gt; (only &lt;code&gt;src/main.c&lt;/code&gt;) and substitute pattern &lt;code&gt;src/%.c&lt;/code&gt; to &lt;code&gt;bin/%&lt;/code&gt;. So &lt;code&gt;src/main.c&lt;/code&gt; becomes &lt;code&gt;bin/main&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Similar for &lt;code&gt;OBJS&lt;/code&gt;: Take all &lt;code&gt;LIB_SRCS&lt;/code&gt; (for example &lt;code&gt;src/vec/vec.c&lt;/code&gt;) and substitute pattern &lt;code&gt;src/%.c&lt;/code&gt; to &lt;code&gt;obj/%.o&lt;/code&gt;. So now the &lt;code&gt;%&lt;/code&gt; spans multiple directory levels. So &lt;code&gt;src/vec/vec.c&lt;/code&gt; becomes &lt;code&gt;obj/vec/vec.o&lt;/code&gt; because &lt;code&gt;%&lt;/code&gt; matches &lt;code&gt;vec/vec&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With these variables we can create some &lt;code&gt;make&lt;/code&gt; rules.&lt;/p&gt;

&lt;p&gt;First of all, the &lt;code&gt;all&lt;/code&gt; rule can now mean: Build all &lt;code&gt;BINS&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(BINS)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is currently only one file, &lt;code&gt;src/main.c&lt;/code&gt;, but if we add more &lt;code&gt;.c&lt;/code&gt; files directly under &lt;code&gt;src&lt;/code&gt; they will be considered entrypoints and they will be compiled to binaries.&lt;/p&gt;

&lt;p&gt;Because we're explicitly listing our source files like this, we don't have to specify &lt;code&gt;VPATH = $(SRC)&lt;/code&gt; anymore.&lt;/p&gt;

&lt;p&gt;Now we're going to be a bit more explicit about how to link all &lt;code&gt;.o&lt;/code&gt; files into the final binary.&lt;/p&gt;

&lt;p&gt;Previously, we were relying heavily on the implicit rules that &lt;code&gt;make&lt;/code&gt; comes with. But now we've customized things enough such that we have to spell it out:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;$(BINS)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(BIN)/%: $(OBJ)/%.o $(OBJS)&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;@D&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;CC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$^&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is some new exotic syntax we haven't seen before, called a &lt;em&gt;static pattern rule&lt;/em&gt;. We have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;targets&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;target-pattern: prerequisites&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows us to explicitly spell out which exact target files we're gonna make, based on variable &lt;code&gt;$(BINS)&lt;/code&gt;. Each target is then matched against the &lt;em&gt;target-pattern&lt;/em&gt; to extract a part of the target name (called the &lt;em&gt;stem&lt;/em&gt;). This stem is substituted into each of the prerequisites that have a pattern (like &lt;code&gt;$(OBJ)/%.o&lt;/code&gt;) to get the prerequisite names.&lt;/p&gt;

&lt;p&gt;For example: target &lt;code&gt;bin/main&lt;/code&gt;, matched with &lt;code&gt;bin/%&lt;/code&gt; creates stem &lt;code&gt;main&lt;/code&gt;. Substitute stem &lt;code&gt;main&lt;/code&gt; into pattern &lt;code&gt;obj/%.o&lt;/code&gt; creates prerequisite &lt;code&gt;obj/main.o&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The recipe of this rule should look familiar. Just making sure the target's directory exists, and then linking all the &lt;code&gt;.o&lt;/code&gt; files into the final binary executable.&lt;/p&gt;

&lt;p&gt;Since we now store everything we make in either the &lt;code&gt;bin&lt;/code&gt; or &lt;code&gt;obj&lt;/code&gt; directories, we can update the &lt;code&gt;clean&lt;/code&gt; rule to just remove those directories entirely:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;RM&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;BIN&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;OBJ&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The full Makefile now looks like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;CFLAGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-Wall&lt;/span&gt; &lt;span class="nt"&gt;-Wextra&lt;/span&gt;

&lt;span class="nv"&gt;NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; main
&lt;span class="nv"&gt;BIN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; bin
&lt;span class="nv"&gt;OBJ&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; obj
&lt;span class="nv"&gt;SRC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; src

&lt;span class="nv"&gt;EXEC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;BIN&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="p"&gt;$(&lt;/span&gt;NAME&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;BIN_SRCS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;wildcard &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.c&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;LIB_SRCS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;wildcard &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.c&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;BINS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;patsubst &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/%.c,&lt;span class="p"&gt;$(&lt;/span&gt;BIN&lt;span class="p"&gt;)&lt;/span&gt;/%,&lt;span class="p"&gt;$(&lt;/span&gt;BIN_SRCS&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nv"&gt;OBJS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;patsubst &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/%.c,&lt;span class="p"&gt;$(&lt;/span&gt;OBJ&lt;span class="p"&gt;)&lt;/span&gt;/%.o,&lt;span class="p"&gt;$(&lt;/span&gt;LIB_SRCS&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="nl"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(BINS)&lt;/span&gt;

&lt;span class="nl"&gt;$(BINS)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(BIN)/%: $(OBJ)/%.o $(OBJS)&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;@D&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;CC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$^&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt;

&lt;span class="nl"&gt;$(OBJ)/%.o&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(SRC)/%.c&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;@D&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;CC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;CFLAGS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nv"&gt;$&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt;

&lt;span class="nl"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(EXEC)&lt;/span&gt;
    ./&lt;span class="p"&gt;$(&lt;/span&gt;EXEC&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nl"&gt;watch&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    find &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-type&lt;/span&gt; f | entr &lt;span class="nt"&gt;-c&lt;/span&gt; make run

&lt;span class="nl"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;RM&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;BIN&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;OBJ&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;all run watch clean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running make works as expected:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% make
cc -Wall -Wextra -c src/main.c -o obj/main.o
cc -Wall -Wextra -c src/rng/rng.c -o obj/rng/rng.o
cc -Wall -Wextra -c src/vec/vec.c -o obj/vec/vec.o
cc obj/main.o obj/rng/rng.o obj/vec/vec.o -o bin/main
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First we're compiling the three source files to object files. Then we link them together into the final executable. But what about the &lt;code&gt;.d&lt;/code&gt; files?&lt;/p&gt;

&lt;p&gt;We haven't done anything about them, &lt;em&gt;yet&lt;/em&gt;. We just needed this foundation to be able to pattern match all files. Let's add the final pieces.&lt;/p&gt;

&lt;p&gt;We will create a &lt;code&gt;.d&lt;/code&gt; file for every &lt;code&gt;.c&lt;/code&gt; file, so let's make a list of all &lt;code&gt;.c&lt;/code&gt; files called &lt;code&gt;ALL_SRCS&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;ALL_SRCS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;BIN_SRCS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;LIB_SRCS&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's pretty simple, just concatenating the &lt;code&gt;$(BIN_SRCS)&lt;/code&gt; with the &lt;code&gt;$(LIB_SRCS)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now we use those for another &lt;code&gt;patsubst&lt;/code&gt; to get a list of &lt;code&gt;.d&lt;/code&gt; files that we'll store in &lt;code&gt;DEPS&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;DEPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;patsubst &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/%.c,&lt;span class="p"&gt;$(&lt;/span&gt;OBJ&lt;span class="p"&gt;)&lt;/span&gt;/%.d,&lt;span class="p"&gt;$(&lt;/span&gt;ALL_SRCS&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The substitution is exactly the same as the one we have for the &lt;code&gt;.o&lt;/code&gt; files, except we change the extension to &lt;code&gt;.d&lt;/code&gt;. This is because the dependency files will be placed next to their corresponding object files under the &lt;code&gt;obj&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;Now we need to tell the compiler to actually create those &lt;code&gt;.d&lt;/code&gt; files. Specifying the list doesn't do anything (it just helps us import them later).&lt;/p&gt;

&lt;p&gt;All we need to do is add the &lt;code&gt;-MMD&lt;/code&gt; flag to our &lt;code&gt;.o&lt;/code&gt; compilation rule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;$(OBJ)/%.o&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(SRC)/%.c&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;@D&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;CC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;CFLAGS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-MMD&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nv"&gt;$&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we're creating the &lt;code&gt;.d&lt;/code&gt; files. You can see it by running make and checking the &lt;code&gt;obj&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── Makefile
├── bin
│&amp;nbsp;&amp;nbsp; └── main
├── obj
│&amp;nbsp;&amp;nbsp; ├── main.d
│&amp;nbsp;&amp;nbsp; ├── main.o
│&amp;nbsp;&amp;nbsp; ├── rng
│&amp;nbsp;&amp;nbsp; │&amp;nbsp;&amp;nbsp; ├── rng.d
│&amp;nbsp;&amp;nbsp; │&amp;nbsp;&amp;nbsp; └── rng.o
│&amp;nbsp;&amp;nbsp; └── vec
│&amp;nbsp;&amp;nbsp;     ├── vec.d
│&amp;nbsp;&amp;nbsp;     └── vec.o
└── src
    ├── main.c
    ├── rng
    │&amp;nbsp;&amp;nbsp; ├── rng.c
    │&amp;nbsp;&amp;nbsp; └── rng.h
    └── vec
        ├── vec.c
        └── vec.h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can include them into the Makefile with this syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="k"&gt;-include&lt;/span&gt;&lt;span class="sx"&gt; $(DEPS)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's why we created that &lt;code&gt;$(DEPS)&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;We're using &lt;code&gt;-include&lt;/code&gt; here instead of &lt;code&gt;include&lt;/code&gt;. This is so that when one of the &lt;code&gt;.d&lt;/code&gt; files doesn't exist, it's silently ignored. If you use &lt;code&gt;include&lt;/code&gt;, you might encounter something like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% make
Makefile:37: obj/main.d: No such file or directory
Makefile:37: obj/rng/rng.d: No such file or directory
Makefile:37: obj/vec/vec.d: No such file or directory
make: *** No rule to make target `obj/vec/vec.d'.  Stop.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now, lo and behold, we can make everything with &lt;code&gt;make&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% make
cc -Wall -Wextra -MMD -c src/main.c -o obj/main.o
cc -Wall -Wextra -MMD -c src/rng/rng.c -o obj/rng/rng.o
cc -Wall -Wextra -MMD -c src/vec/vec.c -o obj/vec/vec.o
cc obj/main.o obj/rng/rng.o obj/vec/vec.o -o bin/main
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And when we modify one of the header files, &lt;code&gt;make&lt;/code&gt; knows we need to recompile:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;% touch src/rng/rng.h
% make
cc -Wall -Wextra -MMD -c src/main.c -o obj/main.o
cc -Wall -Wextra -MMD -c src/rng/rng.c -o obj/rng/rng.o
cc obj/main.o obj/rng/rng.o obj/vec/vec.o -o bin/main
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It recompiled &lt;code&gt;src/main.c&lt;/code&gt; and &lt;code&gt;src/rng/rng.c&lt;/code&gt; because they both include &lt;code&gt;src/rng/rng.h&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Our &lt;code&gt;watch&lt;/code&gt; rule also works properly now. It was already running &lt;code&gt;make run&lt;/code&gt; on a change of any file inside the &lt;code&gt;src&lt;/code&gt; directory, so that was already working. But now, when a &lt;code&gt;.h&lt;/code&gt; file is the one that's being edited, it will trigger &lt;code&gt;entr&lt;/code&gt; and properly run a recompile.&lt;/p&gt;

&lt;p&gt;A few final tweaks before we sign off.&lt;/p&gt;

&lt;p&gt;If your build needs linker flags, the convention is to split them across two variables. &lt;code&gt;LDFLAGS&lt;/code&gt; holds linker options like &lt;code&gt;-L/opt/lib&lt;/code&gt; and goes &lt;em&gt;before&lt;/em&gt; the object files. &lt;code&gt;LDLIBS&lt;/code&gt; holds the libraries themselves, like &lt;code&gt;-lm&lt;/code&gt;, and goes &lt;em&gt;after&lt;/em&gt; them, because the linker resolves symbols in the order it sees them. That's the same ordering &lt;code&gt;make&lt;/code&gt; uses in its own implicit link rule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;$(BINS)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(BIN)/%: $(OBJ)/%.o $(OBJS)&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;@D&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;CC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;LDFLAGS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$^&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;LDLIBS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can simplify our &lt;code&gt;run&lt;/code&gt; target:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(EXEC)&lt;/span&gt;
    &lt;span class="nv"&gt;$&amp;lt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is very optional, but the magic variable &lt;code&gt;$&amp;lt;&lt;/code&gt; refers to the first prerequisite, which is &lt;code&gt;$(EXEC)&lt;/code&gt;, which is &lt;code&gt;bin/main&lt;/code&gt;. So &lt;code&gt;bin/main&lt;/code&gt; is executed as a command, which runs the main executable.&lt;/p&gt;




&lt;p&gt;And that's it. We've finished our Makefile!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Makefile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;CFLAGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-Wall&lt;/span&gt; &lt;span class="nt"&gt;-Wextra&lt;/span&gt;

&lt;span class="nv"&gt;NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; main
&lt;span class="nv"&gt;BIN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; bin
&lt;span class="nv"&gt;OBJ&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; obj
&lt;span class="nv"&gt;SRC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; src

&lt;span class="nv"&gt;EXEC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;BIN&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="p"&gt;$(&lt;/span&gt;NAME&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;BIN_SRCS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;wildcard &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.c&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;LIB_SRCS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;wildcard &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.c&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;ALL_SRCS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;BIN_SRCS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;LIB_SRCS&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;BINS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;patsubst &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/%.c,&lt;span class="p"&gt;$(&lt;/span&gt;BIN&lt;span class="p"&gt;)&lt;/span&gt;/%,&lt;span class="p"&gt;$(&lt;/span&gt;BIN_SRCS&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nv"&gt;OBJS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;patsubst &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/%.c,&lt;span class="p"&gt;$(&lt;/span&gt;OBJ&lt;span class="p"&gt;)&lt;/span&gt;/%.o,&lt;span class="p"&gt;$(&lt;/span&gt;LIB_SRCS&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nv"&gt;DEPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;patsubst &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt;/%.c,&lt;span class="p"&gt;$(&lt;/span&gt;OBJ&lt;span class="p"&gt;)&lt;/span&gt;/%.d,&lt;span class="p"&gt;$(&lt;/span&gt;ALL_SRCS&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="nl"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(BINS)&lt;/span&gt;

&lt;span class="nl"&gt;$(BINS)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(BIN)/%: $(OBJ)/%.o $(OBJS)&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;@D&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;CC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;LDFLAGS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$^&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;LDLIBS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt;

&lt;span class="nl"&gt;$(OBJ)/%.o&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(SRC)/%.c&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;@D&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;CC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;CFLAGS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-MMD&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nv"&gt;$&amp;lt;&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt;

&lt;span class="nl"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(EXEC)&lt;/span&gt;
    &lt;span class="nv"&gt;$&amp;lt;&lt;/span&gt;

&lt;span class="nl"&gt;watch&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    find &lt;span class="p"&gt;$(&lt;/span&gt;SRC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-type&lt;/span&gt; f | entr &lt;span class="nt"&gt;-c&lt;/span&gt; make run

&lt;span class="nl"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;RM&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;BIN&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;OBJ&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;-include&lt;/span&gt;&lt;span class="sx"&gt; $(DEPS)&lt;/span&gt;

&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;all run watch clean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatically compile everything with &lt;code&gt;make&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Compile and run with &lt;code&gt;make run&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Recompile and run on edits with &lt;code&gt;make watch&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Clean up our mess with &lt;code&gt;make clean&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the Makefile automatically detects our source files.&lt;/p&gt;

&lt;p&gt;Thanks for reading. I hope this gives you the courage to go out into your codebase, whip up a new Makefile from scratch, and automate some of those repetitive commands.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://vanderoost.com/articles/2026/08/05/levels-of-effective-makefile-cheatsheet/" rel="noopener noreferrer"&gt;vanderoost.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/vanderoost/c-makefile-template" rel="noopener noreferrer"&gt;C Makefile template on Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>automation</category>
      <category>cli</category>
      <category>devops</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
