<?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: Avinash Kori</title>
    <description>The latest articles on DEV Community by Avinash Kori (@avinashkori).</description>
    <link>https://dev.to/avinashkori</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%2F4187051%2F43aab64f-6ad4-480d-a2eb-6ddf1d22b947.png</url>
      <title>DEV Community: Avinash Kori</title>
      <link>https://dev.to/avinashkori</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/avinashkori"/>
    <language>en</language>
    <item>
      <title>How I Run a Real C Compiler in the Browser with WebAssembly</title>
      <dc:creator>Avinash Kori</dc:creator>
      <pubDate>Sat, 17 Oct 2026 10:57:11 +0000</pubDate>
      <link>https://dev.to/avinashkori/how-i-run-a-real-c-compiler-in-the-browser-with-webassembly-5375</link>
      <guid>https://dev.to/avinashkori/how-i-run-a-real-c-compiler-in-the-browser-with-webassembly-5375</guid>
      <description>&lt;p&gt;Most online compilers send your code to a server, run it in a container and send the output back. I wanted one where the code never leaves the browser. Here is how the C compiler on &lt;a href="https://devtoolry.com/compilers/c" rel="noopener noreferrer"&gt;Devtoolry&lt;/a&gt; works, and what surprised me along the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pieces
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Clang and LLD compiled to WebAssembly.&lt;/strong&gt; I use the &lt;a href="https://yowasp.org" rel="noopener noreferrer"&gt;YoWASP&lt;/a&gt; build of Clang 21. It is a normal npm package served from jsDelivr, about 23 MB compressed. The browser caches it after the first run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A module Web Worker.&lt;/strong&gt; Compiling and running happen off the main thread, so the page stays responsive and an infinite loop can't freeze the tab.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compile to wasm32-wasi in memory.&lt;/strong&gt; The worker runs &lt;code&gt;clang -std=c17 -O2 -Wall main.c -lm&lt;/code&gt; against an in-memory file system and gets a &lt;code&gt;main.wasm&lt;/code&gt; binary back.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A minimal WASI host.&lt;/strong&gt; The program needs stdin, stdout, stderr, clocks and randomness. It gets no file system and no network, which makes the sandbox simple.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A timeout that kills the worker.&lt;/strong&gt; The page starts a timer when the program starts running (compilation and the first download don't count). If it fires, the page calls &lt;code&gt;worker.terminate()&lt;/code&gt; and shows "Timed out". Terminating a worker is the only reliable way to stop a tight &lt;code&gt;for (;;)&lt;/code&gt; loop.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The core of the run step is short:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;program&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;WebAssembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;binary&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;wasi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createWasi&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;main&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;write&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fd&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stderr&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stdout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;WebAssembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instantiate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;wasi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;status&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ready&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// the page starts the time limit here&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;exitCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;wasi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What behaves differently from native C
&lt;/h2&gt;

&lt;p&gt;Testing with a lot of real beginner programs turned up some differences worth knowing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;32-bit sizes.&lt;/strong&gt; wasm32 means &lt;code&gt;sizeof(long) == 4&lt;/code&gt; and &lt;code&gt;sizeof(void *) == 4&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NULL reads don't crash.&lt;/strong&gt; Address 0 is valid linear memory, so reading through a NULL pointer returns a value (0 in my tests) instead of a segfault. Out-of-bounds access past the end of memory does trap.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No fortified libc.&lt;/strong&gt; A &lt;code&gt;strcpy&lt;/code&gt; overflow that aborts on Ubuntu GCC silently corrupts memory here. Clang still warns at compile time ("'strcpy' will always overflow").&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No interactive stdin.&lt;/strong&gt; Input has to be typed into a box before running, because WASI's stdin is a byte buffer here, not a terminal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turbo C headers.&lt;/strong&gt; &lt;code&gt;conio.h&lt;/code&gt; doesn't exist, and &lt;code&gt;gets()&lt;/code&gt; is rejected because C11 removed it. These are the two most common reasons beginner code fails.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Making C++ fast enough
&lt;/h2&gt;

&lt;p&gt;C++ was the slow one: parsing &lt;code&gt;&amp;lt;iostream&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;vector&amp;gt;&lt;/code&gt; and friends took 5–9 seconds per compile in WebAssembly. A precompiled header of the common standard headers, built once with the exact same Clang version and downloaded in the background, cuts a typical compile to 1–3 seconds. As a bonus, the header list doubles as GCC's &lt;code&gt;&amp;lt;bits/stdc++.h&amp;gt;&lt;/code&gt;, which competitive programmers expect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Was it worth it?
&lt;/h2&gt;

&lt;p&gt;For learning and quick tests, yes. There's no account and no queue, it works on a phone, and privacy comes for free. The trade-offs are the first download and the lack of threads, files and sockets.&lt;/p&gt;

&lt;p&gt;If you want to dig into the C side, I wrote up &lt;a href="https://devtoolry.com/blog/c-pointers-explained" rel="noopener noreferrer"&gt;pointers&lt;/a&gt;, &lt;a href="https://devtoolry.com/blog/strings-in-c" rel="noopener noreferrer"&gt;strings&lt;/a&gt; and &lt;a href="https://devtoolry.com/blog/gcc-vs-clang" rel="noopener noreferrer"&gt;GCC vs Clang&lt;/a&gt; with output from both compilers. Questions about the worker or the WASI shim are welcome in the comments.&lt;/p&gt;

</description>
      <category>c</category>
      <category>webassembly</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Preview HTML Code Online Safely: Sandboxed iframes Explained</title>
      <dc:creator>Avinash Kori</dc:creator>
      <pubDate>Sat, 17 Oct 2026 10:32:04 +0000</pubDate>
      <link>https://dev.to/avinashkori/how-to-preview-html-code-online-safely-sandboxed-iframes-explained-651</link>
      <guid>https://dev.to/avinashkori/how-to-preview-html-code-online-safely-sandboxed-iframes-explained-651</guid>
      <description>&lt;p&gt;Previewing HTML sounds trivial: put the markup in a page and let the browser draw it. It stops being trivial as soon as the HTML comes from somewhere you don't fully trust, such as an email template from a vendor, a snippet from a forum, a file a user uploaded or output from a language model. HTML can carry scripts, forms and links that act with the permissions of whatever page displays it.&lt;/p&gt;

&lt;p&gt;This article explains how to look at any HTML safely: the &lt;code&gt;&amp;lt;iframe sandbox&amp;gt;&lt;/code&gt; attribute, inline documents with &lt;code&gt;srcdoc&lt;/code&gt;, how the Content Security Policy adds a second wall, and why previews sometimes look broken. The same techniques power the &lt;a href="https://devtoolry.com/developer-tools/html-viewer" rel="noopener noreferrer"&gt;HTML Viewer&lt;/a&gt; on this site, which you can use to try every example below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why rendering HTML can be dangerous
&lt;/h2&gt;

&lt;p&gt;When a page inserts HTML into itself, for example with &lt;code&gt;element.innerHTML = untrusted&lt;/code&gt;, that HTML becomes part of the page. Any script it manages to run can read the page's cookies (unless they are HttpOnly), its local storage and everything the user sees, and can send requests as the signed-in user. This is cross-site scripting (XSS), one of the most common web vulnerabilities.&lt;/p&gt;

&lt;p&gt;Scripts don't need a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag. Event handler attributes run code too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"does-not-exist.png"&lt;/span&gt; &lt;span class="na"&gt;onerror=&lt;/span&gt;&lt;span class="s"&gt;"alert('this runs')"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The image fails to load, the &lt;code&gt;onerror&lt;/code&gt; handler fires, and the code runs. Filtering out &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags with a regular expression doesn't make HTML safe; there are far too many ways to run code. There are two reliable approaches: sanitise the HTML with a proven library such as DOMPurify, or render it somewhere it cannot reach your page. For a preview, the second approach is simpler and keeps the markup exactly as written.&lt;/p&gt;

&lt;h2&gt;
  
  
  The sandboxed iframe
&lt;/h2&gt;

&lt;p&gt;An &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; displays a separate document inside a rectangle on the page. The &lt;code&gt;sandbox&lt;/code&gt; attribute puts that document under strict restrictions. With an empty value, everything is switched off:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;iframe&lt;/span&gt; &lt;span class="na"&gt;sandbox&lt;/span&gt; &lt;span class="na"&gt;srcdoc=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;h1&amp;gt;Hello&amp;lt;/h1&amp;gt;&amp;lt;p&amp;gt;Rendered safely.&amp;lt;/p&amp;gt;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a sandboxed frame with no permissions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;scripts don't run, including &lt;code&gt;onerror&lt;/code&gt; and other event handlers;&lt;/li&gt;
&lt;li&gt;forms can't be submitted;&lt;/li&gt;
&lt;li&gt;pop-ups, new windows and modal dialogs are blocked;&lt;/li&gt;
&lt;li&gt;the frame can't navigate the page around it;&lt;/li&gt;
&lt;li&gt;the content gets a unique, opaque origin, so it can't read the parent page's cookies, storage or DOM, even though it was created by that page.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You switch individual capabilities back on by listing them: &lt;code&gt;sandbox="allow-scripts"&lt;/code&gt;, &lt;code&gt;sandbox="allow-forms allow-popups"&lt;/code&gt; and so on. The rule is to grant as little as possible.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;srcdoc&lt;/code&gt; holds the HTML of the framed document directly, so nothing has to be uploaded or served from a URL. That is how an online HTML viewer can render your code entirely in the browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one combination to avoid
&lt;/h2&gt;

&lt;p&gt;Two permissions are dangerous together: &lt;code&gt;allow-scripts&lt;/code&gt; and &lt;code&gt;allow-same-origin&lt;/code&gt;. With both, a framed document that is same-origin with its parent (and a &lt;code&gt;srcdoc&lt;/code&gt; document is) can run a script that reaches into the parent page and removes the sandbox attribute from its own iframe. At that point the sandbox does nothing.&lt;/p&gt;

&lt;p&gt;So a safe preview that needs JavaScript uses &lt;code&gt;sandbox="allow-scripts"&lt;/code&gt; &lt;strong&gt;without&lt;/strong&gt; &lt;code&gt;allow-same-origin&lt;/code&gt;. The scripts run, but in an opaque origin with no access to your page. That is exactly what the HTML Viewer does when you switch on "Run scripts": it adds &lt;code&gt;allow-scripts&lt;/code&gt; (and &lt;code&gt;allow-modals&lt;/code&gt;, so &lt;code&gt;alert()&lt;/code&gt; works) and nothing else.&lt;/p&gt;

&lt;h2&gt;
  
  
  A second wall: Content Security Policy
&lt;/h2&gt;

&lt;p&gt;A sandbox limits what the framed document can do to its parent. A Content Security Policy (CSP) limits what any document on the site can load and run. An &lt;code&gt;srcdoc&lt;/code&gt; iframe inherits the CSP of the page that creates it, so if the site only allows scripts from its own origin, a preview can't load a script from a random CDN either, even with scripts enabled.&lt;/p&gt;

&lt;p&gt;This is why a pasted snippet with &lt;code&gt;&amp;lt;script src="https://example.com/library.js"&amp;gt;&lt;/code&gt; may not work in a preview while inline &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; blocks do. It is a deliberate trade-off: the preview shows your markup and inline code, but it can't be used to pull in arbitrary third-party code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why your preview looks broken
&lt;/h2&gt;

&lt;p&gt;Most "the preview is wrong" problems have one of these causes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Relative URLs.&lt;/strong&gt; &lt;code&gt;src="images/logo.png"&lt;/code&gt; or &lt;code&gt;href="style.css"&lt;/code&gt; are resolved against a base URL, and an inline document has no folder to resolve them against. Use absolute &lt;code&gt;https://&lt;/code&gt; URLs, or add a &lt;code&gt;&amp;lt;base href="https://your-site.example/"&amp;gt;&lt;/code&gt; tag inside the snippet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Missing styles.&lt;/strong&gt; The framed document is isolated, so it doesn't inherit the CSS of the page around it. Add a &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; block or link a public stylesheet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scripts switched off.&lt;/strong&gt; Content generated by JavaScript (frameworks, charts, sliders) stays empty until scripts are allowed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forms do nothing.&lt;/strong&gt; Submitting is blocked in the sandbox, which is what you want for untrusted markup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server-side templates.&lt;/strong&gt; PHP, Razor (&lt;code&gt;.cshtml&lt;/code&gt;), JSX or Jinja code is executed on a server before a browser ever sees it. Paste the HTML the server produces, not the template, or the directives appear as plain text.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hard-to-read markup is another common complaint. Run minified or machine-generated HTML through the &lt;a href="https://devtoolry.com/developer-tools/html-formatter" rel="noopener noreferrer"&gt;HTML Formatter&lt;/a&gt; first, and the structure becomes obvious.&lt;/p&gt;

&lt;h2&gt;
  
  
  Previewing HTML emails
&lt;/h2&gt;

&lt;p&gt;HTML emails are a common reason to need a quick preview. A viewer shows how a browser renders the markup, which is a good first check of the layout, images and links. Email clients are stricter than browsers, though: some ignore &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; blocks, most block scripts entirely, and many need tables for layout and inline &lt;code&gt;style&lt;/code&gt; attributes. Treat a browser preview as a draft check, and test the final email in the real clients your readers use.&lt;/p&gt;

&lt;p&gt;The same goes for meta tags and social cards: a viewer renders the visible page, while tags in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; only matter to search engines and social networks. Our guide to &lt;a href="https://devtoolry.com/blog/html-meta-tags-for-seo" rel="noopener noreferrer"&gt;HTML meta tags for SEO&lt;/a&gt; explains which ones count.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to see the HTML of any web page
&lt;/h2&gt;

&lt;p&gt;To inspect how an existing page is built, open its source in the browser with &lt;strong&gt;Ctrl+U&lt;/strong&gt; (Cmd+Option+U in Chrome on a Mac), or put &lt;code&gt;view-source:&lt;/code&gt; in front of the address. You can copy parts of that source into a viewer to render them in isolation, for example to debug a single card or table.&lt;/p&gt;

&lt;p&gt;Keep in mind that the source is the HTML the server sent. Pages built by JavaScript frameworks may contain little more than an empty &lt;code&gt;&amp;lt;div id="root"&amp;gt;&lt;/code&gt;; the browser's developer tools (F12, Elements tab) show the live document after scripts have run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Never insert untrusted HTML directly into a page: event handlers like &lt;code&gt;onerror&lt;/code&gt; run code even without &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags.&lt;/li&gt;
&lt;li&gt;Render previews in an &lt;code&gt;&amp;lt;iframe sandbox&amp;gt;&lt;/code&gt; with &lt;code&gt;srcdoc&lt;/code&gt;. An empty sandbox blocks scripts, forms, pop-ups and access to the parent page.&lt;/li&gt;
&lt;li&gt;If scripts are needed, use &lt;code&gt;allow-scripts&lt;/code&gt; alone. Never combine it with &lt;code&gt;allow-same-origin&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A CSP adds a second layer by controlling what any document can load.&lt;/li&gt;
&lt;li&gt;Broken previews usually come down to relative URLs, missing styles or disabled scripts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Paste your markup into the &lt;a href="https://devtoolry.com/developer-tools/html-viewer" rel="noopener noreferrer"&gt;HTML Viewer&lt;/a&gt; to see it rendered safely as you type. When it looks right, the &lt;a href="https://devtoolry.com/converters/html-to-pdf" rel="noopener noreferrer"&gt;HTML to PDF&lt;/a&gt; converter turns the same HTML into a document, and the &lt;a href="https://devtoolry.com/developer-tools/html-entity-encoder-decoder" rel="noopener noreferrer"&gt;HTML Entity Encoder&lt;/a&gt; escapes code samples you want to show as text rather than render.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://devtoolry.com/blog/preview-html-safely" rel="noopener noreferrer"&gt;Devtoolry&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>html</category>
      <category>security</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Pointers in C Explained: Addresses, Arrays and Memory with Runnable Examples</title>
      <dc:creator>Avinash Kori</dc:creator>
      <pubDate>Sat, 17 Oct 2026 10:31:31 +0000</pubDate>
      <link>https://dev.to/avinashkori/pointers-in-c-explained-addresses-arrays-and-memory-with-runnable-examples-4nko</link>
      <guid>https://dev.to/avinashkori/pointers-in-c-explained-addresses-arrays-and-memory-with-runnable-examples-4nko</guid>
      <description>&lt;p&gt;Pointers are the part of C that decides whether the language feels simple or impossible. The rules are small: a pointer is a variable that stores an address, &lt;code&gt;&amp;amp;&lt;/code&gt; takes an address and &lt;code&gt;*&lt;/code&gt; follows one. The difficulty comes from what those rules make possible: functions that change their arguments, arrays that turn into pointers, memory you allocate and must free yourself.&lt;/p&gt;

&lt;p&gt;This guide builds that up one step at a time. Every program below was compiled and run with Clang 21 in the &lt;a href="https://devtoolry.com/compilers/c" rel="noopener noreferrer"&gt;online C Compiler&lt;/a&gt; and with GCC 11, and the output shown is the real output. Paste any of them into the compiler, change a line and run it again: that is the fastest way to make pointers click.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a pointer is
&lt;/h2&gt;

&lt;p&gt;Every variable lives somewhere in memory, and that location has an address. A pointer is a variable whose value is such an 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="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="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;int&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&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;score&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;"score = %d&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;score&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;"*p    = %d&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="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&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;"p == &amp;amp;score: %s&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;p&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;score&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s"&gt;"yes"&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"no"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="o"&gt;*&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;99&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;"score after *p = 99: %d&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;score&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;score = 42
*p    = 42
p == &amp;amp;score: yes
score after *p = 99: 99
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read the declarations out loud and they make sense:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;int *p&lt;/code&gt; declares &lt;code&gt;p&lt;/code&gt; as a "pointer to int".&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;amp;score&lt;/code&gt; is "the address of score".&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;*p&lt;/code&gt; is "the int that p points to". Reading it gives 42; assigning to it changes &lt;code&gt;score&lt;/code&gt;, because &lt;code&gt;*p&lt;/code&gt; and &lt;code&gt;score&lt;/code&gt; are the same memory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;*&lt;/code&gt; has two jobs, which is the first source of confusion. In a declaration (&lt;code&gt;int *p&lt;/code&gt;) it says "this is a pointer". In an expression (&lt;code&gt;*p = 99&lt;/code&gt;) it means "follow the pointer". The two uses are related but not the same thing.&lt;/p&gt;

&lt;p&gt;You can print an address with &lt;code&gt;printf("%p\n", (void *)p)&lt;/code&gt;, but the number changes from run to run and machine to machine, so it is rarely useful except to see that two pointers are equal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why functions need pointers
&lt;/h2&gt;

&lt;p&gt;C passes every argument by value: the function receives a copy. That is why this classic swap does nothing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;swap_wrong&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;a&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;b&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;tmp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;swap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;b&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;tmp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="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;x&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;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;swap_wrong&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&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;"after swap_wrong: x=%d y=%d&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;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;swap&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;x&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;y&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;"after swap:       x=%d y=%d&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;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;after swap_wrong: x=1 y=2
after swap:       x=2 y=1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;swap_wrong&lt;/code&gt; swaps its own copies, which disappear when it returns. &lt;code&gt;swap&lt;/code&gt; receives the &lt;em&gt;addresses&lt;/em&gt; of &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;, so &lt;code&gt;*a&lt;/code&gt; and &lt;code&gt;*b&lt;/code&gt; are the caller's variables. This is also why &lt;code&gt;scanf("%d", &amp;amp;n)&lt;/code&gt; needs the &lt;code&gt;&amp;amp;&lt;/code&gt;: scanf has to write into your variable, so it needs its address. Our guide to &lt;a href="https://devtoolry.com/blog/reading-input-in-c-and-cpp" rel="noopener noreferrer"&gt;reading input in C and C++&lt;/a&gt; covers the scanf side in detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pointers and arrays
&lt;/h2&gt;

&lt;p&gt;An array name used in an expression turns ("decays") into a pointer to its first element. That is why indexing and pointer arithmetic are interchangeable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;show_size&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;arr&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;"inside function: sizeof arr = %zu&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="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;nums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nums&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;"nums[2] = %d, *(nums + 2) = %d, p[2] = %d&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;nums&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="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;p&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="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"in main: sizeof nums = %zu&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt; &lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;show_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nums[2] = 30, *(nums + 2) = 30, p[2] = 30
in main: sizeof nums = 20
inside function: sizeof arr = 4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;nums[2]&lt;/code&gt; is defined as &lt;code&gt;*(nums + 2)&lt;/code&gt;, so all three expressions read the same element. The surprise is the last line. In &lt;code&gt;main&lt;/code&gt;, &lt;code&gt;nums&lt;/code&gt; is a real array of five 4-byte ints, 20 bytes. In &lt;code&gt;show_size&lt;/code&gt;, the parameter &lt;code&gt;int arr[]&lt;/code&gt; is really &lt;code&gt;int *arr&lt;/code&gt;, so &lt;code&gt;sizeof&lt;/code&gt; gives the size of a pointer: 4 bytes in the WebAssembly build of the online compiler, 8 bytes with GCC on a 64-bit PC. Both compilers warn about it (&lt;code&gt;-Wsizeof-array-argument&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The practical rule: &lt;strong&gt;a function never knows the length of an array you pass it.&lt;/strong&gt; Pass the length as a separate argument, as every standard function from &lt;code&gt;qsort&lt;/code&gt; to &lt;code&gt;fgets&lt;/code&gt; does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pointer arithmetic
&lt;/h2&gt;

&lt;p&gt;Adding 1 to a pointer moves it to the next &lt;em&gt;element&lt;/em&gt;, not the next byte. The compiler scales by the size of the type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&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;double&lt;/span&gt; &lt;span class="n"&gt;prices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&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;9&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&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;75&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;first&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;prices&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="kt"&gt;double&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;last&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;prices&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="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"elements between: %td&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;last&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;first&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;"bytes between:    %td&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="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;total&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;double&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prices&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;prices&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="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&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;"total: %.2f&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;total&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;elements between: 2
bytes between:    16
total: 25.50
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Subtracting two pointers into the same array gives the number of elements between them (type &lt;code&gt;ptrdiff_t&lt;/code&gt;, printed with &lt;code&gt;%td&lt;/code&gt;). Casting to &lt;code&gt;char *&lt;/code&gt; shows the bytes: two doubles of 8 bytes each. The loop walks the array with a pointer instead of an index, a style you will see often in older C code. Pointing one past the last element (&lt;code&gt;prices + 3&lt;/code&gt;) is allowed as a loop end; reading through it is not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Allocating memory with malloc and free
&lt;/h2&gt;

&lt;p&gt;Arrays declared inside a function vanish when it returns. When the size is known only at run time, or the data must outlive the function, allocate it on the heap:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;make_squares&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;n&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="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;malloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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;a&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;a&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;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;n&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="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;a&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;i&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;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="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;n&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="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;make_squares&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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;sq&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"out of memory&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;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;n&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="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;"%d "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sq&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="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="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sq&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;sq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0 1 4 9 16 25
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three habits make heap code safe. Write &lt;code&gt;n * sizeof *a&lt;/code&gt; rather than &lt;code&gt;n * sizeof(int)&lt;/code&gt;, so the size stays right if the type changes. Check for &lt;code&gt;NULL&lt;/code&gt;, because &lt;code&gt;malloc&lt;/code&gt; can fail. And call &lt;code&gt;free&lt;/code&gt; exactly once for every successful &lt;code&gt;malloc&lt;/code&gt;, then set the pointer to &lt;code&gt;NULL&lt;/code&gt; so an accidental second &lt;code&gt;free&lt;/code&gt; or later use is easy to spot.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pointers to pointers
&lt;/h2&gt;

&lt;p&gt;A function that must change &lt;em&gt;which address&lt;/em&gt; the caller's pointer holds needs a pointer to that pointer, &lt;code&gt;char **&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;#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;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;duplicate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&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;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;malloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="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;strcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;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;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;duplicate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"devtoolry"&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;name&lt;/span&gt;&lt;span class="p"&gt;)&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;"copy: %s (%zu chars)&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;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;copy: devtoolry (9 chars)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is the same idea as &lt;code&gt;swap&lt;/code&gt;: to change an &lt;code&gt;int&lt;/code&gt; you pass an &lt;code&gt;int *&lt;/code&gt;; to change a &lt;code&gt;char *&lt;/code&gt; you pass a &lt;code&gt;char **&lt;/code&gt;. The &lt;code&gt;+ 1&lt;/code&gt; in the &lt;code&gt;malloc&lt;/code&gt; call makes room for the string's terminating &lt;code&gt;'\0'&lt;/code&gt;, which &lt;code&gt;strlen&lt;/code&gt; does not count.&lt;/p&gt;

&lt;h2&gt;
  
  
  const and pointers
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;const&lt;/code&gt; can protect the data, the pointer, or both, depending on where it goes:&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;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;int&lt;/span&gt; &lt;span class="n"&gt;a&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;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&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;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;q&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;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;*&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;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;q&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;b&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;main.c:5:8: error: read-only variable is not assignable
    5 |     *p = 5;
      |     ~~ ^
main.c:6:7: error: cannot assign to variable 'q' with const-qualified type 'int *const'
    6 |     q = &amp;amp;b;
      |     ~ ^
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read the declaration from right to left. &lt;code&gt;const int *p&lt;/code&gt; is "a pointer to a constant int": you can move &lt;code&gt;p&lt;/code&gt;, but not change the int through it. &lt;code&gt;int *const q&lt;/code&gt; is "a constant pointer to an int": you can change the int, but &lt;code&gt;q&lt;/code&gt; always points to &lt;code&gt;a&lt;/code&gt;. Function parameters such as &lt;code&gt;const char *src&lt;/code&gt; in &lt;code&gt;duplicate&lt;/code&gt; above promise the caller that the function will not modify their data.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bugs pointers cause
&lt;/h2&gt;

&lt;p&gt;Most pointer bugs fall into a few groups:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Uninitialised pointers.&lt;/strong&gt; &lt;code&gt;int *p; *p = 1;&lt;/code&gt; writes to a random address. Initialise every pointer, to &lt;code&gt;NULL&lt;/code&gt; if nothing else.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dangling pointers.&lt;/strong&gt; Returning the address of a local variable, or using memory after &lt;code&gt;free&lt;/code&gt;. The program may appear to work, and different compilers behave differently: for &lt;code&gt;int *broken(void) { int local = 7; return &amp;amp;local; }&lt;/code&gt;, GCC at &lt;code&gt;-O2&lt;/code&gt; returns &lt;code&gt;NULL&lt;/code&gt; while Clang returns the stale address. Both warn, so never ignore that warning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Off-by-one access.&lt;/strong&gt; Reading &lt;code&gt;a[n]&lt;/code&gt; in an array of &lt;code&gt;n&lt;/code&gt; elements. C does not check bounds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory leaks.&lt;/strong&gt; Losing the only pointer to allocated memory before freeing it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Double free.&lt;/strong&gt; Calling &lt;code&gt;free&lt;/code&gt; twice on the same pointer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Compiler warnings catch a surprising number of these. Always compile with &lt;code&gt;-Wall&lt;/code&gt; (the online compiler does), read every warning, and when a program crashes, look at the compiler errors guide and the line numbers the compiler gives you. Printing values and addresses step by step is still the most effective debugging tool for pointer code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A pointer stores an address. &lt;code&gt;&amp;amp;x&lt;/code&gt; gets the address of &lt;code&gt;x&lt;/code&gt;; &lt;code&gt;*p&lt;/code&gt; reads or writes the value at that address.&lt;/li&gt;
&lt;li&gt;C passes arguments by value, so functions that change the caller's variables take pointers.&lt;/li&gt;
&lt;li&gt;Arrays decay to pointers. &lt;code&gt;a[i]&lt;/code&gt; is &lt;code&gt;*(a + i)&lt;/code&gt;, and a function cannot know an array's length unless you pass it.&lt;/li&gt;
&lt;li&gt;Pointer arithmetic counts elements, not bytes.&lt;/li&gt;
&lt;li&gt;Every &lt;code&gt;malloc&lt;/code&gt; needs a &lt;code&gt;NULL&lt;/code&gt; check and exactly one &lt;code&gt;free&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Read &lt;code&gt;const&lt;/code&gt; declarations right to left.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try changing the examples in the &lt;a href="https://devtoolry.com/compilers/c" rel="noopener noreferrer"&gt;C Compiler&lt;/a&gt;: remove an &lt;code&gt;&amp;amp;&lt;/code&gt;, pass the wrong length, free twice, and read what the compiler and the program say. If you prefer containers to raw pointers, the same programs can be rewritten with &lt;code&gt;std::vector&lt;/code&gt; in the &lt;a href="https://devtoolry.com/compilers/cpp" rel="noopener noreferrer"&gt;C++ Compiler&lt;/a&gt;, and the &lt;a href="https://devtoolry.com/converters/number-base-converter" rel="noopener noreferrer"&gt;Number Base Converter&lt;/a&gt; helps when you print addresses or bit patterns in hex.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://devtoolry.com/blog/c-pointers-explained" rel="noopener noreferrer"&gt;Devtoolry&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>c</category>
      <category>programming</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>JWT Explained: Structure, Claims and How to Verify a Token</title>
      <dc:creator>Avinash Kori</dc:creator>
      <pubDate>Thu, 15 Oct 2026 15:18:53 +0000</pubDate>
      <link>https://dev.to/avinashkori/jwt-explained-structure-claims-and-how-to-verify-a-token-43a8</link>
      <guid>https://dev.to/avinashkori/jwt-explained-structure-claims-and-how-to-verify-a-token-43a8</guid>
      <description>&lt;p&gt;JSON Web Tokens (JWTs) are everywhere in modern authentication: OAuth and OpenID Connect use them, single-page apps send them in &lt;code&gt;Authorization&lt;/code&gt; headers, and microservices pass them to each other. They are also widely misunderstood. A JWT is not encrypted, decoding one is not the same as verifying it, and a few common shortcuts turn them into a security hole.&lt;/p&gt;

&lt;p&gt;This guide takes a real token apart, explains every piece, and lists the checks your server must make before trusting one.&lt;/p&gt;

&lt;h2&gt;
  
  
  A real token, taken apart
&lt;/h2&gt;

&lt;p&gt;Here is a complete JWT, signed with HS256 and the secret &lt;code&gt;correct-horse-battery-staple&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;eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyXzEyMyIsIm5hbWUiOiJBZGEgTG92ZWxhY2UiLCJyb2xlIjoiYWRtaW4iLCJpYXQiOjE3OTIwNTEyMDAsImV4cCI6MTc5MjA1NDgwMH0.mEEzS78g7k66oYCyIa17SFw9_XR6J_6u5wH_eyT1qI0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It looks like random text, but it's three parts separated by dots: &lt;strong&gt;header&lt;/strong&gt;, &lt;strong&gt;payload&lt;/strong&gt; and &lt;strong&gt;signature&lt;/strong&gt;. The first two are just JSON encoded with Base64URL (Base64 with &lt;code&gt;-&lt;/code&gt; and &lt;code&gt;_&lt;/code&gt; instead of &lt;code&gt;+&lt;/code&gt; and &lt;code&gt;/&lt;/code&gt;, and no &lt;code&gt;=&lt;/code&gt; padding). Decode them and you get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"alg"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HS256"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"typ"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"JWT"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&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 json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sub"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user_123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ada Lovelace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"iat"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1792051200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"exp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1792054800&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste the token into the &lt;a href="https://devtoolry.com/developer-tools/jwt-decoder" rel="noopener noreferrer"&gt;JWT Decoder&lt;/a&gt; to see the same thing, with the timestamps converted to readable dates. It runs in your browser, which matters: pasting a production token into a website that sends it to a server is a real leak.&lt;/p&gt;

&lt;p&gt;The important lesson is already visible: &lt;strong&gt;anyone who has the token can read the payload.&lt;/strong&gt; There is no secret involved in decoding. Never put passwords, API keys or personal data you wouldn't show the user into a JWT payload. If you need confidentiality, use encrypted tokens (JWE) or keep the data on the server.&lt;/p&gt;

&lt;h2&gt;
  
  
  The header
&lt;/h2&gt;

&lt;p&gt;The header says how the token was signed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;alg&lt;/code&gt; is the signing algorithm. &lt;code&gt;HS256&lt;/code&gt; means HMAC with SHA-256 using a shared secret. &lt;code&gt;RS256&lt;/code&gt; and &lt;code&gt;ES256&lt;/code&gt; use a private key to sign and a public key to verify.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;typ&lt;/code&gt; is usually &lt;code&gt;JWT&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kid&lt;/code&gt; (key ID), when present, tells the verifier which key to use, which makes key rotation possible.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The payload and its claims
&lt;/h2&gt;

&lt;p&gt;The payload holds &lt;em&gt;claims&lt;/em&gt;: statements about the user and the token. Some names are registered by the JWT standard (RFC 7519):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Claim&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;iss&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Issuer: who created the token&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://auth.example.com&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sub&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Subject: who the token is about&lt;/td&gt;
&lt;td&gt;&lt;code&gt;user_123&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;aud&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Audience: who the token is meant for&lt;/td&gt;
&lt;td&gt;&lt;code&gt;api.example.com&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;exp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Expiration time (Unix seconds)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1792054800&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nbf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Not valid before (Unix seconds)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1792051200&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;iat&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Issued at (Unix seconds)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1792051200&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jti&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Unique token ID (for revocation lists)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;9f1c…&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All times are &lt;strong&gt;Unix timestamps in seconds&lt;/strong&gt;, not milliseconds. &lt;code&gt;exp: 1792054800&lt;/code&gt; is 15 October 2026 at 09:00 UTC, exactly one hour after &lt;code&gt;iat&lt;/code&gt;. Mixing up seconds and milliseconds is a classic bug: &lt;code&gt;Date.now()&lt;/code&gt; in JavaScript returns milliseconds, so a token created with &lt;code&gt;exp: Date.now() + 3600&lt;/code&gt; expires in the year 58,000-something. Our guide to &lt;a href="https://devtoolry.com/blog/unix-timestamps-explained" rel="noopener noreferrer"&gt;Unix timestamps&lt;/a&gt; covers this trap and others.&lt;/p&gt;

&lt;p&gt;Anything else in the payload (&lt;code&gt;name&lt;/code&gt;, &lt;code&gt;role&lt;/code&gt;) is a custom claim your application defines.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the signature works
&lt;/h2&gt;

&lt;p&gt;The signature is what makes a JWT trustworthy. For HS256 it is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HMAC-SHA256(secret, base64url(header) + "." + base64url(payload))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;encoded with Base64URL. The server that issued the token computes this with its secret. Later, to verify the token, a server recomputes the HMAC over the first two parts and compares it with the third. If someone changes even one character of the payload (say, &lt;code&gt;"role": "user"&lt;/code&gt; to &lt;code&gt;"role": "admin"&lt;/code&gt;), the signature no longer matches, and the token is rejected.&lt;/p&gt;

&lt;p&gt;With asymmetric algorithms (RS256, ES256), the issuer signs with a private key and anyone with the public key can verify. That's the standard choice when many services need to verify tokens but only one should be able to create them; the identity provider publishes its public keys at a JWKS URL.&lt;/p&gt;

&lt;p&gt;You can see this in action with the &lt;a href="https://devtoolry.com/developer-tools/jwt-generator" rel="noopener noreferrer"&gt;JWT Generator&lt;/a&gt;: sign a payload, change one claim in the decoder, and watch verification fail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verifying a token step by step
&lt;/h2&gt;

&lt;p&gt;Decoding is easy. Verifying means checking all of the following, in this order, and rejecting the token if any check fails:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The algorithm is the one you expect.&lt;/strong&gt; Configure your verifier with an allow-list (for example, only &lt;code&gt;RS256&lt;/code&gt;). Never let the token's own &lt;code&gt;alg&lt;/code&gt; header decide.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The signature is valid&lt;/strong&gt; for the key you trust.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;exp&lt;/code&gt; is in the future&lt;/strong&gt; and &lt;code&gt;nbf&lt;/code&gt;, if present, is in the past. Allow a small clock skew (30–60 seconds) between servers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;iss&lt;/code&gt; is your identity provider&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;aud&lt;/code&gt; is your service.&lt;/strong&gt; A token issued for a different application, even by the same provider, must not work on yours.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application rules&lt;/strong&gt;: the user still exists, the token hasn't been revoked, the claimed role is allowed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is what steps 1–3 look like with Node.js's built-in &lt;code&gt;crypto&lt;/code&gt;, to show there is no magic involved:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createHmac&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timingSafeEqual&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:crypto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decodePart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;part&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;part&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;base64url&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;verifyHs256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;decodePart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;h&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="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alg&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HS256&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Unexpected algorithm &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alg&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createHmac&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sha256&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;base64url&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;timingSafeEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bad signature&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;claims&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;decodePart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&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="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;claims&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exp&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;claims&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Token expired&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;claims&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 &lt;code&gt;timingSafeEqual&lt;/code&gt;: comparing signatures with &lt;code&gt;===&lt;/code&gt; can leak, through response timing, how many leading bytes matched. In production, use a maintained library rather than this sketch. With the popular &lt;code&gt;jose&lt;/code&gt; package, the full check is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;jwtVerify&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jose&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;secret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TextEncoder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JWT_SECRET&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;jwtVerify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;algorithms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HS256&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;issuer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://auth.example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;audience&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;api.example.com&lt;/span&gt;&lt;span class="dl"&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;h2&gt;
  
  
  Security mistakes to avoid
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Decoding instead of verifying.&lt;/strong&gt; Functions like &lt;code&gt;jwt.decode()&lt;/code&gt; only read the payload. Using them to make authorisation decisions means anyone can forge a token by editing the JSON. Always verify.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trusting &lt;code&gt;alg&lt;/code&gt; from the token.&lt;/strong&gt; Early libraries accepted &lt;code&gt;"alg": "none"&lt;/code&gt; (no signature at all), and some could be tricked into verifying an RS256 token as HS256 using the &lt;em&gt;public&lt;/em&gt; key as the HMAC secret. Both attacks are stopped by an algorithm allow-list.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weak HMAC secrets.&lt;/strong&gt; An HS256 token can be brute-forced offline: an attacker with one token can try millions of secrets per second until the signature matches. Use at least 32 random bytes (256 bits), such as a 64-character hex string from the &lt;a href="https://devtoolry.com/generators/random-string-generator" rel="noopener noreferrer"&gt;Random String Generator&lt;/a&gt;. Our article on password entropy explains why length and randomness matter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Long lifetimes.&lt;/strong&gt; A JWT can't easily be revoked before it expires, because verification doesn't involve a database. Keep access tokens short-lived (5–15 minutes) and use refresh tokens, which &lt;em&gt;are&lt;/em&gt; stored and revocable, to get new ones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Storing tokens in &lt;code&gt;localStorage&lt;/code&gt;.&lt;/strong&gt; Any script on your page (including one injected through an XSS bug or a compromised dependency) can read &lt;code&gt;localStorage&lt;/code&gt;. For browser apps, an &lt;code&gt;HttpOnly&lt;/code&gt;, &lt;code&gt;Secure&lt;/code&gt;, &lt;code&gt;SameSite&lt;/code&gt; cookie keeps the token out of reach of JavaScript. If you use cookies, protect state-changing requests against CSRF.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sensitive data in the payload.&lt;/strong&gt; Repeat after me: the payload is only encoded, not encrypted. The &lt;a href="https://devtoolry.com/developer-tools/base64-encoder-decoder" rel="noopener noreferrer"&gt;Base64 decoder&lt;/a&gt; is all anyone needs to read it, as our guide to &lt;a href="https://devtoolry.com/blog/base64-encoding-explained" rel="noopener noreferrer"&gt;Base64 encoding&lt;/a&gt; shows.&lt;/p&gt;

&lt;h2&gt;
  
  
  JWTs or sessions?
&lt;/h2&gt;

&lt;p&gt;JWTs shine when different services must verify identity without calling a central database, which is the reason OAuth and OpenID Connect use them. For a single web application with its own backend, a classic session (a random ID in a cookie, looked up on the server) is simpler, can be revoked instantly, and keeps nothing readable on the client. Choose JWTs for what they're good at, not because they're fashionable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;A JWT is a Base64URL-encoded header and payload plus a signature over both. Anyone can read it; only the holder of the key can create a valid one. Before trusting a token, check the algorithm against an allow-list, verify the signature, and validate &lt;code&gt;exp&lt;/code&gt;, &lt;code&gt;nbf&lt;/code&gt;, &lt;code&gt;iss&lt;/code&gt; and &lt;code&gt;aud&lt;/code&gt;. Use strong secrets, short lifetimes and safe storage, and keep secrets out of the payload.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://devtoolry.com/blog/jwt-explained" rel="noopener noreferrer"&gt;Devtoolry&lt;/a&gt;, where you can also &lt;a href="https://devtoolry.com/developer-tools/jwt-decoder" rel="noopener noreferrer"&gt;decode and verify JWTs in your browser&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
