{
  "description": "Browse aymeric's, an independent, searchable archive of readable snapshots from followed feeds, preserved in Git with aggr.",
  "feed_url": "https://aggr.aymericbeaumet.com/sources/abner.page/feed.json",
  "home_page_url": "https://aggr.aymericbeaumet.com/sources/abner.page/",
  "items": [
    {
      "authors": [
        {
          "name": "abner.page by abnercoimbre"
        }
      ],
      "content_html": "<p>This is one of a three-part mini series about how I’m using modern C as of late 2026.</p>\n<p>Before C23, I was <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://www.youtube.com/watch?v=443UNeGrFoM\">taken in</a> by <em>How I Program C</em> for years and years, and would even feel guilty for choosing C99 instead of <code>-ansi -pedantic</code>. But holy crap man I’m done being a doomsday prepper! These days I maintain a large-enough project with enough users where I could stand less foot-shooting. (I’ve also got bills to pay.)</p>\n<p>So here’s three modern C conventions which started to rise naturally from adding <code>-std=c23</code> to my zig build:</p>\n<h2>1. Unused? Maybe. (Yes)</h2>\n<p>Our first convention is centered around <code>[[nodiscard]]</code>. If I draw an app window or panel I require the caller to interrogate the rect of the thing that was just rendered:</p>\n<pre><code class=\"language-c\"><span class=\"code-snippet\" data-language=\"C\"><span class=\"syntax-source syntax-c\"><span class=\"syntax-meta syntax-brackets syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-begin syntax-c\">[</span><span class=\"syntax-meta syntax-brackets syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-begin syntax-c\">[</span>nodiscard<span class=\"syntax-punctuation syntax-section syntax-brackets syntax-end syntax-c\">]</span></span><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-end syntax-c\">]</span></span> rect_t <span class=\"syntax-meta syntax-function-call syntax-c\"><span class=\"syntax-variable syntax-function syntax-c\">draw_screen</span><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-c\">(</span></span></span><span class=\"syntax-meta syntax-function-call syntax-c\"><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-comment syntax-block syntax-c\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-c\">/*</span> ... <span class=\"syntax-punctuation syntax-definition syntax-comment syntax-c\">*/</span></span></span></span><span class=\"syntax-meta syntax-function-call syntax-c\"><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-c\">)</span></span></span> <span class=\"syntax-meta syntax-block syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-c\">{</span>\n    rect_t screen_r <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-c\">=</span> <span class=\"syntax-meta syntax-block syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-c\">{</span> <span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-c\">}</span></span><span class=\"syntax-punctuation syntax-terminator syntax-c\">;</span>\n    <span class=\"syntax-comment syntax-line syntax-double-slash syntax-c\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-c\">//</span> Draw stuff\n</span>    <span class=\"syntax-comment syntax-line syntax-double-slash syntax-c\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-c\">//</span> ...\n</span>    <span class=\"syntax-keyword syntax-control syntax-c\">return</span> screen_r<span class=\"syntax-punctuation syntax-terminator syntax-c\">;</span>\n<span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-c\">}</span></span>\n</span></span></code></pre>\n<p>It’s a genuine business logic bug if the caller doesn’t capture the rectangle for later processing. Therefore <code>[[nodiscard]]</code> has been such a godsend for fixing bugs… Except there’s a choice few instances where I will draw something with <em>no real use</em> for the resulting rect. I’d rather ignore the return value:</p>\n<pre><code class=\"language-c\"><span class=\"code-snippet\" data-language=\"C\"><span class=\"syntax-source syntax-c\"><span class=\"syntax-storage syntax-type syntax-c\">enum</span> screen_opt popup_options <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-c\">=</span> <span class=\"syntax-comment syntax-block syntax-c\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-c\">/*</span> ... <span class=\"syntax-punctuation syntax-definition syntax-comment syntax-c\">*/</span></span> <span class=\"syntax-punctuation syntax-terminator syntax-c\">;</span>\n<span class=\"syntax-meta syntax-function-call syntax-c\"><span class=\"syntax-variable syntax-function syntax-c\">draw_screen</span><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-c\">(</span></span></span><span class=\"syntax-meta syntax-function-call syntax-c\"><span class=\"syntax-meta syntax-group syntax-c\">popup_options<span class=\"syntax-punctuation syntax-separator syntax-c\">,</span> <span class=\"syntax-comment syntax-block syntax-c\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-c\">/*</span> ... <span class=\"syntax-punctuation syntax-definition syntax-comment syntax-c\">*/</span></span></span><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-c\">)</span></span></span><span class=\"syntax-punctuation syntax-terminator syntax-c\">;</span> <span class=\"syntax-comment syntax-line syntax-double-slash syntax-c\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-c\">//</span> ERROR: damn you [[nodiscard]]\n</span></span></span></code></pre>\n<p>Clang will error out here. I could maybe capture the var and never use it but…</p>\n<pre><code class=\"language-c\"><span class=\"code-snippet\" data-language=\"C\"><span class=\"syntax-source syntax-c\">rect_t rect <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-c\">=</span> <span class=\"syntax-meta syntax-function-call syntax-c\"><span class=\"syntax-variable syntax-function syntax-c\">draw_screen</span><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-c\">(</span></span></span><span class=\"syntax-meta syntax-function-call syntax-c\"><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-comment syntax-block syntax-c\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-c\">/*</span> ... <span class=\"syntax-punctuation syntax-definition syntax-comment syntax-c\">*/</span></span></span></span><span class=\"syntax-meta syntax-function-call syntax-c\"><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-c\">)</span></span></span><span class=\"syntax-punctuation syntax-terminator syntax-c\">;</span> <span class=\"syntax-comment syntax-line syntax-double-slash syntax-c\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-c\">//</span> ERROR: unused variable (I have `-Werror` enabled)\n</span></span></span></code></pre>\n<p>Pre-C23 one might solve this through an <code>UNUSED()</code> macro:</p>\n<pre><code class=\"language-c\"><span class=\"code-snippet\" data-language=\"C\"><span class=\"syntax-source syntax-c\"><span class=\"syntax-meta syntax-preprocessor syntax-c\"><span class=\"syntax-keyword syntax-control syntax-import syntax-c\">#ifndef</span> UNUSED\n</span><span class=\"syntax-meta syntax-preprocessor syntax-macro syntax-c\"><span class=\"syntax-keyword syntax-control syntax-import syntax-define syntax-c\">#define</span></span><span class=\"syntax-meta syntax-preprocessor syntax-macro syntax-c\"> <span class=\"syntax-entity syntax-name syntax-function syntax-preprocessor syntax-c\">UNUSED</span></span><span class=\"syntax-meta syntax-preprocessor syntax-macro syntax-parameters syntax-c\"><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-c\">(</span><span class=\"syntax-variable syntax-parameter syntax-c\">x</span><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-c\">)</span></span></span><span class=\"syntax-meta syntax-preprocessor syntax-macro syntax-c\"> <span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-c\">(</span><span class=\"syntax-storage syntax-type syntax-c\">void</span><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-c\">)</span></span><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-c\">(</span>x<span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-c\">)</span></span></span>\n<span class=\"syntax-meta syntax-preprocessor syntax-c\"><span class=\"syntax-keyword syntax-control syntax-import syntax-c\">#endif</span></span>\n\nrect_t rect <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-c\">=</span> <span class=\"syntax-meta syntax-function-call syntax-c\"><span class=\"syntax-variable syntax-function syntax-c\">draw_screen</span><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-c\">(</span></span></span><span class=\"syntax-meta syntax-function-call syntax-c\"><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-comment syntax-block syntax-c\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-c\">/*</span> ... <span class=\"syntax-punctuation syntax-definition syntax-comment syntax-c\">*/</span></span></span></span><span class=\"syntax-meta syntax-function-call syntax-c\"><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-c\">)</span></span></span><span class=\"syntax-punctuation syntax-terminator syntax-c\">;</span>\n<span class=\"syntax-meta syntax-function-call syntax-c\"><span class=\"syntax-variable syntax-function syntax-c\">UNUSED</span><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-c\">(</span></span></span><span class=\"syntax-meta syntax-function-call syntax-c\"><span class=\"syntax-meta syntax-group syntax-c\">rect</span><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-c\">)</span></span></span><span class=\"syntax-punctuation syntax-terminator syntax-c\">;</span> <span class=\"syntax-comment syntax-line syntax-double-slash syntax-c\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-c\">//</span> Silences the compiler, but now I&#39;m sad.\n</span></span></span></code></pre>\n<p>But now with C23 we can delete the macro in favor of the native <code>[[maybe_unused]]</code>:</p>\n<pre><code class=\"language-c\"><span class=\"code-snippet\" data-language=\"C\"><span class=\"syntax-source syntax-c\"><span class=\"syntax-meta syntax-brackets syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-begin syntax-c\">[</span><span class=\"syntax-meta syntax-brackets syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-begin syntax-c\">[</span>maybe_unused<span class=\"syntax-punctuation syntax-section syntax-brackets syntax-end syntax-c\">]</span></span><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-end syntax-c\">]</span></span> rect_t rect <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-c\">=</span> <span class=\"syntax-meta syntax-function-call syntax-c\"><span class=\"syntax-variable syntax-function syntax-c\">draw_screen</span><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-c\">(</span></span></span><span class=\"syntax-meta syntax-function-call syntax-c\"><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-keyword syntax-operator syntax-variadic syntax-c\">...</span></span></span><span class=\"syntax-meta syntax-function-call syntax-c\"><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-c\">)</span></span></span><span class=\"syntax-punctuation syntax-terminator syntax-c\">;</span> <span class=\"syntax-comment syntax-line syntax-double-slash syntax-c\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-c\">//</span> OK\n</span></span></span></code></pre>\n<p>Phew I feel better. I’ve also noticed this is happening all over the place: lots of different routines returning different types that are marked with <code>[[nodiscard]]</code>. So for all the unused cases why not just go for:</p>\n<pre><code class=\"language-c\"><span class=\"code-snippet\" data-language=\"C\"><span class=\"syntax-source syntax-c\"><span class=\"syntax-meta syntax-brackets syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-begin syntax-c\">[</span><span class=\"syntax-meta syntax-brackets syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-begin syntax-c\">[</span>maybe_unused<span class=\"syntax-punctuation syntax-section syntax-brackets syntax-end syntax-c\">]</span></span><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-end syntax-c\">]</span></span> <span class=\"syntax-storage syntax-type syntax-c\">auto</span> _ <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-c\">=</span> <span class=\"syntax-meta syntax-function-call syntax-c\"><span class=\"syntax-variable syntax-function syntax-c\">foo</span><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-c\">(</span></span></span><span class=\"syntax-meta syntax-function-call syntax-c\"></span><span class=\"syntax-meta syntax-function-call syntax-c\"><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-c\">)</span></span></span><span class=\"syntax-punctuation syntax-terminator syntax-c\">;</span> <span class=\"syntax-comment syntax-line syntax-double-slash syntax-c\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-c\">//</span> A new pattern emerges\n</span></span></span></code></pre>\n<p>Bonus: For any macro fans out there a fellow indie dev (Zardium) offered an additional improvement. From our chat server:</p>\n<blockquote>\n<p>Zardium: #define _ [[maybe_unused]] auto CONCAT_MACRO(zz,<strong>COUNTER</strong>)</p>\n</blockquote>\n<blockquote>\n<p>Abner: ahh, unique varname. nice one</p>\n</blockquote>\n<blockquote>\n<p>Zardium: you could take the auto out if you don’t want it to look so weird. then it acts exactly like the _ in other languages, where it can be redefined</p>\n</blockquote>\n<blockquote>\n<p>Abner: Yep totally. Although here I was celebrating my removal of a macro… XD</p>\n</blockquote>\n<h2>2. More Perfect Unions</h2>\n<p>I’ve been cheated and lied to: designated initializers DO NOT clear my struct to zero and I can’t even trust <code>{0}</code> anymore. (Talk about a betrayal.) The problem is I’ll often have data types like this contrived timestamp:</p>\n<pre><code class=\"language-c\"><span class=\"code-snippet\" data-language=\"C\"><span class=\"syntax-source syntax-c\"><span class=\"syntax-storage syntax-type syntax-c\">typedef</span> <span class=\"syntax-storage syntax-type syntax-c\">struct</span> <span class=\"syntax-meta syntax-block syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-c\">{</span>\n    Type type<span class=\"syntax-punctuation syntax-terminator syntax-c\">;</span>\n    <span class=\"syntax-storage syntax-type syntax-c\">char</span> buf<span class=\"syntax-meta syntax-brackets syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-begin syntax-c\">[</span>MAX<span class=\"syntax-punctuation syntax-section syntax-brackets syntax-end syntax-c\">]</span></span><span class=\"syntax-punctuation syntax-terminator syntax-c\">;</span>\n    <span class=\"syntax-storage syntax-type syntax-c\">union</span> <span class=\"syntax-meta syntax-block syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-c\">{</span>\n        <span class=\"syntax-support syntax-type syntax-sys-types syntax-c\">time_t</span> time<span class=\"syntax-punctuation syntax-terminator syntax-c\">;</span>\n        <span class=\"syntax-storage syntax-type syntax-c\">float</span> dt<span class=\"syntax-punctuation syntax-terminator syntax-c\">;</span>\n        date_t date<span class=\"syntax-punctuation syntax-terminator syntax-c\">;</span>\n    <span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-c\">}</span></span><span class=\"syntax-punctuation syntax-terminator syntax-c\">;</span>\n<span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-c\">}</span></span> <span class=\"syntax-entity syntax-name syntax-type syntax-typedef syntax-c\">stamp_t</span><span class=\"syntax-punctuation syntax-terminator syntax-c\">;</span>\n</span></span></code></pre>\n<p>And if I partially initialize one:</p>\n<pre><code class=\"language-c\"><span class=\"code-snippet\" data-language=\"C\"><span class=\"syntax-source syntax-c\">stamp_t stamp <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-c\">=</span> <span class=\"syntax-meta syntax-block syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-c\">{</span> <span class=\"syntax-punctuation syntax-accessor syntax-c\">.</span><span class=\"syntax-variable syntax-other syntax-member syntax-c\">type</span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-c\">=</span> STAMP_TYPE_BLA_BLA <span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-c\">}</span></span><span class=\"syntax-punctuation syntax-terminator syntax-c\">;</span>\n</span></span></code></pre>\n<p>While it does mean we successfully zeroed out <code>buf</code> (thanks to <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://en.cppreference.com/c/language/initialization#Empty_initialization\">empty initialization</a>), those union members are just a different beast. It also doesn’t matter if we go with <code>stamp_t stamp = {0}</code> instead. My dear reader: I’ve made the costly mistake of assuming <code>date</code> would clear to zero!</p>\n<p>As I Spongebob-panicked in public, Lobsters member <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://lobste.rs/~accelbread\">accelbread</a> offered a sage revelation:</p>\n<blockquote>\n<p>accelbread: It used to be that GCC would fully zero the union anyways, and clang would only zero the time_t, though around a year ago they swapped behaviors iirc. Either way, standard only requires the time_t be zeroed and not whole union. GCC has a flag to always zero whole union. Also C23 initialization always inits whole union</p>\n</blockquote>\n<p>Wait WHAT? clang and gcc SWAPPED what now? I won’t investigate further. Everything about this is <em>dangerous af</em> unless we hug C23 tightly and never let go:</p>\n<pre><code class=\"language-c\"><span class=\"code-snippet\" data-language=\"C\"><span class=\"syntax-source syntax-c\">stamp_t stamp <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-c\">=</span> <span class=\"syntax-meta syntax-block syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-c\">{</span> <span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-c\">}</span></span><span class=\"syntax-punctuation syntax-terminator syntax-c\">;</span> <span class=\"syntax-comment syntax-line syntax-double-slash syntax-c\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-c\">//</span> Fully clears to zero (C23)\n</span>stamp<span class=\"syntax-punctuation syntax-accessor syntax-c\">.</span><span class=\"syntax-variable syntax-other syntax-member syntax-c\">type</span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-c\">=</span> STAMP_TYPE_BLA_BLA<span class=\"syntax-punctuation syntax-terminator syntax-c\">;</span>\n</span></span></code></pre>\n<p>Accelbread went on to say two more things:</p>\n<ol>\n<li><em>“Note the C23 zero init whole thing is nothing in the brackets, not 0 in brackets; { 0 } does same thing as before C23”</em></li>\n<li><em>“Also if you control union layout, putting largest member first is safest”</em></li>\n</ol>\n<p>Yessir.</p>\n<h2>3. Enums In C Were Magic (And I Don’t Like It)</h2>\n<p>If I want to customize some dialog box I’ll use bit flags:</p>\n<pre><code class=\"language-c\"><span class=\"code-snippet\" data-language=\"C\"><span class=\"syntax-source syntax-c\"><span class=\"syntax-meta syntax-enum syntax-c\"><span class=\"syntax-storage syntax-type syntax-c\">enum</span> <span class=\"syntax-meta syntax-block syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-c\">{</span></span></span><span class=\"syntax-meta syntax-enum syntax-c\"><span class=\"syntax-meta syntax-block syntax-c\">\n    OPT_AUTOSCROLL <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-c\">=</span> <span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-c\">(</span><span class=\"syntax-constant syntax-numeric syntax-c\">1</span> <span class=\"syntax-keyword syntax-operator syntax-arithmetic syntax-c\">&lt;&lt;</span> <span class=\"syntax-constant syntax-numeric syntax-c\">0</span><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-c\">)</span></span><span class=\"syntax-punctuation syntax-separator syntax-c\">,</span>\n    OPT_NOCURSOR   <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-c\">=</span> <span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-c\">(</span><span class=\"syntax-constant syntax-numeric syntax-c\">1</span> <span class=\"syntax-keyword syntax-operator syntax-arithmetic syntax-c\">&lt;&lt;</span> <span class=\"syntax-constant syntax-numeric syntax-c\">1</span><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-c\">)</span></span><span class=\"syntax-punctuation syntax-separator syntax-c\">,</span>\n    OPT_CENTERED   <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-c\">=</span> <span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-c\">(</span><span class=\"syntax-constant syntax-numeric syntax-c\">1</span> <span class=\"syntax-keyword syntax-operator syntax-arithmetic syntax-c\">&lt;&lt;</span> <span class=\"syntax-constant syntax-numeric syntax-c\">2</span><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-c\">)</span></span><span class=\"syntax-punctuation syntax-separator syntax-c\">,</span>\n    OPT_NOCLOSE    <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-c\">=</span> <span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-c\">(</span><span class=\"syntax-constant syntax-numeric syntax-c\">1</span> <span class=\"syntax-keyword syntax-operator syntax-arithmetic syntax-c\">&lt;&lt;</span> <span class=\"syntax-constant syntax-numeric syntax-c\">3</span><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-c\">)</span></span><span class=\"syntax-punctuation syntax-separator syntax-c\">,</span>\n    <span class=\"syntax-comment syntax-line syntax-double-slash syntax-c\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-c\">//</span> ...\n</span></span></span><span class=\"syntax-meta syntax-enum syntax-c\"><span class=\"syntax-meta syntax-block syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-c\">}</span></span></span><span class=\"syntax-punctuation syntax-terminator syntax-c\">;</span>\n\n<span class=\"syntax-meta syntax-brackets syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-begin syntax-c\">[</span><span class=\"syntax-meta syntax-brackets syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-begin syntax-c\">[</span>nodiscard<span class=\"syntax-punctuation syntax-section syntax-brackets syntax-end syntax-c\">]</span></span><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-end syntax-c\">]</span></span> <span class=\"syntax-storage syntax-type syntax-c\">bool</span> <span class=\"syntax-meta syntax-function-call syntax-c\"><span class=\"syntax-variable syntax-function syntax-c\">draw_warning</span><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-c\">(</span></span></span><span class=\"syntax-meta syntax-function-call syntax-c\"><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-storage syntax-modifier syntax-c\">const</span> <span class=\"syntax-storage syntax-type syntax-c\">char</span><span class=\"syntax-keyword syntax-operator syntax-c\">*</span> msg<span class=\"syntax-punctuation syntax-separator syntax-c\">,</span> <span class=\"syntax-storage syntax-type syntax-c\">int</span> opt</span></span><span class=\"syntax-meta syntax-function-call syntax-c\"><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-c\">)</span></span></span><span class=\"syntax-punctuation syntax-terminator syntax-c\">;</span>\n</span></span></code></pre>\n<p>Even if we disagree with this approach lots of relevant libraries or projects do it:</p>\n<pre><code class=\"language-c\"><span class=\"code-snippet\" data-language=\"C\"><span class=\"syntax-source syntax-c\">_ <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-c\">=</span> <span class=\"syntax-meta syntax-function-call syntax-c\"><span class=\"syntax-variable syntax-function syntax-c\">draw_warning</span><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-c\">(</span></span></span><span class=\"syntax-meta syntax-function-call syntax-c\"><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-string syntax-quoted syntax-double syntax-c\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-c\">&quot;</span>you done messed up A-A-RON<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-c\">&quot;</span></span><span class=\"syntax-punctuation syntax-separator syntax-c\">,</span> OPT_CENTERED <span class=\"syntax-keyword syntax-operator syntax-arithmetic syntax-c\">|</span> OPT_NOCLOSE</span></span><span class=\"syntax-meta syntax-function-call syntax-c\"><span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-c\">)</span></span></span><span class=\"syntax-punctuation syntax-terminator syntax-c\">;</span>\n</span></span></code></pre>\n<p>Of course, erroneous bit shifting will land anyone into trouble and yield comical numbers. Thankfully C enums are a plain <code>int</code> underneath so the compiler will warn us if we defined a bad constant inside the enum that won’t fit.</p>\n<p>:)</p>\n<p>I’m kidding. Sigh. Well, I’m growing fearful of sage revelations but this one comes from <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://gustedt.gitlabpages.inria.fr/modern-c/\">Modern C</a> by Jens Gustedt:</p>\n<blockquote>\n<p>Jens: If enumeration constants do not fit into signed int, if possible, the enumeration type is adjusted such that it can store all enumeration constants.</p>\n</blockquote>\n<p>Noooooo!</p>\n<blockquote>\n<p>Jens: The property that an an enumeration type is adjusted such that it fits all its constants could have surprising effects</p>\n</blockquote>\n<p><em>sobs</em></p>\n<blockquote>\n<p>Jens: So, it is preferable to specify the underlying integer type explicitly</p>\n</blockquote>\n<p>THERE IS HOPE?</p>\n<pre><code class=\"language-c\"><span class=\"code-snippet\" data-language=\"C\"><span class=\"syntax-source syntax-c\"><span class=\"syntax-meta syntax-enum syntax-c\"><span class=\"syntax-storage syntax-type syntax-c\">enum</span> <span class=\"syntax-entity syntax-name syntax-enum syntax-c\">options</span> : <span class=\"syntax-entity syntax-name syntax-enum syntax-c\">int</span> <span class=\"syntax-meta syntax-block syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-begin syntax-c\">{</span></span></span><span class=\"syntax-meta syntax-enum syntax-c\"><span class=\"syntax-meta syntax-block syntax-c\">\n    OPT_AUTOSCROLL <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-c\">=</span> <span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-c\">(</span><span class=\"syntax-constant syntax-numeric syntax-c\">1</span> <span class=\"syntax-keyword syntax-operator syntax-arithmetic syntax-c\">&lt;&lt;</span> <span class=\"syntax-constant syntax-numeric syntax-c\">0</span><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-c\">)</span></span><span class=\"syntax-punctuation syntax-separator syntax-c\">,</span>\n    OPT_NOCURSOR   <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-c\">=</span> <span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-c\">(</span><span class=\"syntax-constant syntax-numeric syntax-c\">1</span> <span class=\"syntax-keyword syntax-operator syntax-arithmetic syntax-c\">&lt;&lt;</span> <span class=\"syntax-constant syntax-numeric syntax-c\">1</span><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-c\">)</span></span><span class=\"syntax-punctuation syntax-separator syntax-c\">,</span>\n    OPT_CENTERED   <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-c\">=</span> <span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-c\">(</span><span class=\"syntax-constant syntax-numeric syntax-c\">1</span> <span class=\"syntax-keyword syntax-operator syntax-arithmetic syntax-c\">&lt;&lt;</span> <span class=\"syntax-constant syntax-numeric syntax-c\">2</span><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-c\">)</span></span><span class=\"syntax-punctuation syntax-separator syntax-c\">,</span>\n    OPT_NOCLOSE    <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-c\">=</span> <span class=\"syntax-meta syntax-group syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-c\">(</span><span class=\"syntax-constant syntax-numeric syntax-c\">1</span> <span class=\"syntax-keyword syntax-operator syntax-arithmetic syntax-c\">&lt;&lt;</span> <span class=\"syntax-constant syntax-numeric syntax-c\">3</span><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-c\">)</span></span><span class=\"syntax-punctuation syntax-separator syntax-c\">,</span>\n    <span class=\"syntax-comment syntax-line syntax-double-slash syntax-c\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-c\">//</span> ...\n</span></span></span><span class=\"syntax-meta syntax-enum syntax-c\"><span class=\"syntax-meta syntax-block syntax-c\"><span class=\"syntax-punctuation syntax-section syntax-block syntax-end syntax-c\">}</span></span></span><span class=\"syntax-punctuation syntax-terminator syntax-c\">;</span>\n</span></span></code></pre>\n<p>It compiles! We shoot. We score. We stick with C23.</p>\n<h2>Epilogue</h2>\n<p>In part two of our mini series I’ll discuss three more conventions that I’ve fleshed out thanks to modern C: starting with safer macro usage (forgive me Zig folks.)</p>\n<p><em>P.S. If you want to shape this discussion <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://handmadecities.com/chat\">maybe join</a> the Handmade Cities server!</em></p>\n<p>-Abner</p>\n",
      "date_modified": "2026-10-15T15:32:15+00:00",
      "date_published": "2026-10-15T15:32:15+00:00",
      "external_url": "https://abner.page/post/c23-conventions-1/",
      "id": "urn:aggr:item:30606cb70eb4e7f84f6bdd70afea228b1000544d",
      "summary": "Comments",
      "tags": [
        "news",
        "c"
      ],
      "title": "My C23 Conventions",
      "url": "https://aggr.aymericbeaumet.com/items/lobste-rs/2026-10-15-my-c23-conventions/"
    }
  ],
  "language": "en",
  "title": "abner.page",
  "version": "https://jsonfeed.org/version/1.1"
}