<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Alyoussefaseel on Medium]]></title>
        <description><![CDATA[Stories by Alyoussefaseel on Medium]]></description>
        <link>https://medium.com/@alyoussefaseel?source=rss-b0d682973368------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*2QYhJowkwquKx2LC</url>
            <title>Stories by Alyoussefaseel on Medium</title>
            <link>https://medium.com/@alyoussefaseel?source=rss-b0d682973368------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Thu, 05 Nov 2026 01:18:07 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@alyoussefaseel/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[So Why Do We Usually Just Type gcc main.c?]]></title>
            <link>https://medium.com/@alyoussefaseel/i-typed-gcc-main-c-but-what-actually-happened-9152b8cafbf5?source=rss-b0d682973368------2</link>
            <guid isPermaLink="false">https://medium.com/p/9152b8cafbf5</guid>
            <category><![CDATA[computer-science]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[c-programming-language]]></category>
            <category><![CDATA[programming-for-beginners]]></category>
            <category><![CDATA[learning-to-code]]></category>
            <dc:creator><![CDATA[Alyoussefaseel]]></dc:creator>
            <pubDate>Wed, 04 Nov 2026 14:35:16 GMT</pubDate>
            <atom:updated>2026-11-04T15:27:23.415Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8tAK5tcRuFAY0tRoJL79Jw.jpeg" /><figcaption><em>“Photo of Codes on Walls” by Beyza Kaplan, via Pexels. Used under the </em><a href="https://www.pexels.com/license/"><em>Pexels License</em></a><em>.</em></figcaption></figure><p><em>⁠</em></p><p><em>One command, four stages, and a surprisingly interesting journey from C code to a working program.</em></p><p>When I started learning C at Holberton School, I noticed something: <strong>GCC seemed to appear everywhere.</strong></p><p>gcc -E, gcc -S, gcc -c…</p><p>Same three letters, different commands, and somehow different files appearing every time.</p><p>As someone coming from a business background, I had a simple question:</p><p><strong>Why do we need all these steps just to make a computer run our code?</strong></p><p>So I decided to look beyond the commands and understand what actually happens behind the scenes.</p><p>And it turns out that typing gcc main.c starts an entire production process.</p><h3>First, Meet GCC</h3><p><strong>GCC stands for GNU Compiler Collection.</strong></p><p>It’s a collection of tools that helps translate programming languages, including C, into instructions a computer can execute.</p><p>Think of GCC as a factory.</p><p>You provide the raw material (your C code), and GCC coordinates the steps needed to turn it into a finished product (an executable program).</p><p>And like any production process, there are stages.</p><p><strong>Here’s the journey:</strong></p><p>main.c → Preprocessing → Compilation → Assembly → Linking → Executable</p><p>Let’s follow a simple program through each one.</p><h3>Our Starting Point: A C Program</h3><p>Imagine we write this inside a file called main.c:</p><pre>#include &lt;stdio.h&gt;</pre><pre>int main(void)<br>{<br>    puts(&quot;Hello, world!&quot;);<br>    return 0;<br>}</pre><p>Nothing complicated. We just want to display Hello, world!.</p><p>But here’s the catch: <strong>writing a C program doesn’t automatically make it runnable.</strong></p><p>The computer needs it translated into machine instructions first.</p><p>That’s GCC’s job.</p><h3>1. Preprocessing: Preparing the Ingredients</h3><p>Before GCC can translate our C code, it needs to prepare it.</p><p>That’s what the <strong>preprocessor</strong> does.</p><p>For example, remember this line?</p><pre>#include &lt;stdio.h&gt;</pre><p>It tells the preprocessor to include the contents of the header file, making declarations such as puts available to the compiler.</p><p>The preprocessor also handles macros (code substitutions) and conditional compilation instructions.</p><p>To see the result, we use:</p><pre>gcc -E main.c -o main.i</pre><p>Here’s what we’re saying:</p><ul><li>gcc — Use GCC.</li><li>-E — Stop after preprocessing.</li><li>main.c — Read our original file.</li><li>-o main.i — Save the result as main.i.</li></ul><p>The .i extension is commonly used for preprocessed C code.</p><p><strong>Our result: </strong><strong>main.i — preprocessed C code, but not yet a runnable program.</strong></p><h3>2. Compilation: Translating the Instructions</h3><p>Now the actual translation begins.</p><p>The compiler converts the preprocessed C code into <strong>assembly language</strong>.</p><p>Assembly is a low-level language that describes operations much closer to what a processor understands.</p><p>To generate assembly, we use:</p><pre>gcc -S main.i -o main.s</pre><p>Notice the capital S!</p><p>It tells GCC to stop after generating assembly code.</p><p>Open main.s, and you may see instructions such as mov, call, and ret, depending on your computer&#39;s processor architecture.</p><p>They probably won’t look like the C code we started with.</p><p>And that’s the point: we’re getting closer to the machine’s language.</p><p><strong>Our result: </strong><strong>main.s — assembly instructions.</strong></p><p>But we’re not finished yet.</p><h3>3. Assembly: Creating Machine Code</h3><p>Here’s where things get interesting.</p><p>The previous stage produced assembly language, which is still readable text.</p><p>Now the <strong>assembler</strong> transforms those instructions into machine code.</p><p>Machine code is the binary representation of instructions that a processor can execute.</p><p>We can produce an object file using:</p><pre>gcc -c main.s -o main.o</pre><p>The lowercase -c tells GCC to compile or assemble the source into an object file without linking it.</p><p>And .o means <strong>object file</strong>.</p><p>If you try opening main.o in an ordinary text editor, you&#39;ll probably see strange symbols.</p><p>That’s because an object file contains machine code and other technical information, not normal text.</p><p>But wait.</p><p><strong>If we already have machine code, why can’t we run it?</strong></p><p>Because an object file isn’t necessarily a complete program. It may still contain unresolved references to functions and other code.</p><p>Which brings us to the final stage.</p><h3>4. Linking: Putting Everything Together</h3><p>Imagine organizing a business event.</p><p>You’ve prepared the speakers, venue, schedule, and equipment. Everything exists, but it still needs to work together.</p><p>That’s similar to what the <strong>linker</strong> does.</p><p>Our program uses puts, which is provided by the C standard library.</p><p>The linker resolves references to external functions and combines the required object files and libraries to produce the final executable.</p><p>Let’s finish:</p><pre>gcc main.o -o hello</pre><p>We’ve now created an executable named hello.</p><p>Time to run it:</p><pre>./hello</pre><p>And the result?</p><pre>Hello, world!</pre><p>Finally!</p><p>We went from a C file to a working program.</p><h3>So Why Do We Usually Just Type gcc main.c?</h3><p>Here’s the best part.</p><p><strong>We don’t need to run each stage separately every time.</strong></p><p>When we type:</p><pre>gcc main.c</pre><p>GCC normally coordinates all four stages automatically.</p><p>On Ubuntu, the default executable is named a.out, unless we choose another name.</p><p>We can run it with:</p><pre>./a.out</pre><p>One distinction worth remembering:</p><p><strong>gcc main.c builds the program.</strong></p><p><strong>./a.out runs the program.</strong></p><p>They are two completely different actions.</p><h3>The GCC Cheat Sheet I Wish I Had Earlier</h3><p>CommandMeaningResultgcc -E main.c -o main.iPreprocess onlymain.igcc -S main.i -o main.sGenerate assemblymain.sgcc -c main.s -o main.oAssemble without linkingmain.ogcc main.o -o helloLink the object filehellogcc main.cRun all stages automaticallya.outgcc main.c -o helloBuild with a chosen executable namehello./helloRun the executableProgram output</p><p>A tiny detail that makes a big difference: <strong>-S and </strong><strong>-c are GCC options, while </strong><strong>.s, </strong><strong>.c, and </strong><strong>.o are file extensions.</strong> Similar letters, completely different purposes.</p><h3>My Biggest Takeaway</h3><p>At first, I thought gcc main.c was just another command I needed to memorize.</p><p>But now I see it differently.</p><p>Our C code doesn’t magically become a working program. It moves through a series of transformations, and each stage solves a specific problem.</p><p>That’s what makes understanding the process more useful than memorizing the commands.</p><p>And I think that’s one of the most interesting things about learning computer science: <strong>behind every simple action, there’s usually a whole system working together.</strong></p><p>So next time I type gcc main.c, I&#39;ll know there&#39;s much more happening behind those few characters.</p><p><strong>One command. Four stages. A working program.</strong></p><p><strong>Further reading:</strong> <a href="https://gcc.gnu.org/onlinedocs/gcc/Overall-Options.html">GCC Official Documentation — Overall Options</a></p><p><em>Part of my C programming learning journey at Holberton School.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9152b8cafbf5" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>