{"id":4163,"date":"2022-05-27T08:30:00","date_gmt":"2022-05-27T06:30:00","guid":{"rendered":"https:\/\/msalamon.pl\/?p=4163"},"modified":"2025-12-27T15:41:31","modified_gmt":"2025-12-27T14:41:31","slug":"project-file-structure-in-c-introduction","status":"publish","type":"post","link":"https:\/\/msalamon.pl\/en\/project-file-structure-in-c-introduction\/","title":{"rendered":"Project File Structure in C &#8211; Introduction"},"content":{"rendered":"\n<p>I\u2019d like to make an introduction to splitting a project into files in the C language. We also need this in order to understand what a module or a compilation unit is.<\/p>\n\n\n\n<p>A good understanding of the concept of a \u201ccompilation unit\u201d will make it so that later you\u2019ll be better oriented in visibility scopes, e.g., of variables. Additionally, you\u2019ll better understand what compilation is and what linking is.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Why split into files?<\/h1>\n\n\n\n<p>When you write your program, 20000% <strong>it will start taking up a lot of lines.<\/strong> Navigating a program with 1,000 lines starts to become cumbersome:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Scrolling is very inconvenient<\/li>\n\n\n\n<li>It\u2019s hard to find things we\u2019re interested in if we didn\u2019t strictly follow some order<\/li>\n\n\n\n<li>\u2026and with order as well<\/li>\n<\/ul>\n\n\n\n<p>Think that, for example, Windows has around <strong>a million<\/strong> lines. I heard that a few years ago, so the newest ones probably already have a few million.<\/p>\n\n\n\n<p><strong>How to live?!<\/strong><\/p>\n\n\n\n<p>Finally, you need to <strong>start splitting the program into smaller modules.<\/strong> These modules will be sets of files that we later include in the main program, or we connect them with each other.<\/p>\n\n\n\n<p>We may already know such modules from the standard library! All external libraries like, for example, string.h are exactly such separate sets of files. We call them <strong>libraries<\/strong>.<\/p>\n\n\n\n<p>When writing your own programs for microcontrollers, you\u2019ll also be writing such libraries for various purposes. Handling a sensor, handling a menu, some graphics. These will be <strong>individual modules.<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Files in the C language<\/h2>\n\n\n\n<p>What files do we have in C? The most important ones and the ones that interest us are <strong>files with the extensions *.c and *.h.<\/strong><\/p>\n\n\n\n<p><strong>H files<\/strong><\/p>\n\n\n\n<p>This is a <strong>header<\/strong>. This is where there will be<strong> only prototypes and declarations.<\/strong><\/p>\n\n\n\n<p>Such a file has no executable code. Or in other words\u2026 we don\u2019t want it to have any \ud83d\ude42<\/p>\n\n\n\n<p>In it we will write the <strong>so-called interface.<\/strong> This will be only what we can use when using this file, or more precisely, the library.<\/p>\n\n\n\n<p>Speaking plainly\u2026 Here you\u2019ll find things such as declarations of:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>types<\/li>\n\n\n\n<li>enums<\/li>\n\n\n\n<li>structures<\/li>\n\n\n\n<li>functions, i.e., only prototypes<\/li>\n\n\n\n<li>global variables (if we want them ;))<\/li>\n<\/ul>\n\n\n\n<p><strong>There will be no executable code here, i.e., function bodies.<\/strong><\/p>\n\n\n\n<p>A set of such declarations <strong>we will include into the second type of file<\/strong> (with the extension *.c). For example, into main.c.<\/p>\n\n\n\n<p>We need to use the preprocessor for this purpose.<\/p>\n\n\n\n<p><strong>#include \u201cfile.h\u201d<\/strong><\/p>\n\n\n\n<p><strong>#include &lt;file.h&gt;<\/strong><\/p>\n\n\n\n<p>With angle brackets &lt;file.h&gt; you indicate a file from the compiler\u2019s default path.<\/p>\n\n\n\n<p>With quotation marks you specify a file from the project path.<\/p>\n\n\n\n<p><strong>C files<\/strong><\/p>\n\n\n\n<p>Files with the extension <strong>*.c are source files<\/strong>. In short, <strong>sources<\/strong>.<\/p>\n\n\n\n<p>This is <strong>the place for the actual code<\/strong>. Here we write function bodies.<\/p>\n\n\n\n<p>Into this file we also include other headers like, for example, the main header main.h or stdio.h.<\/p>\n\n\n\n<p>This file must know the <strong>definitions <\/strong>of the types it works on, as well as other headers that will be required to compile this file.<\/p>\n\n\n\n<p>Apart from functions, we can place global variables here. They will be able to be visible globally, i.e., throughout the entire project. Only\u2026 this will be rare and truly a <strong>last resort <\/strong>. In good practice we rather avoid global variables. I\u2019ll talk more about that someday.<\/p>\n\n\n\n<p>If not global, then what? <strong>Globals with a limited scope<\/strong> to this specific file. This is a much better and more common practice.<\/p>\n\n\n\n<p>I guess I\u2019ll have to talk about those globals earlier. Let me know if I should do that in the next emails.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Minimum for the compiler<\/h2>\n\n\n\n<p>This may seem surprising, but you need to know that the <strong>compiler <\/strong>to compile a file<strong> needs only definitions.<\/strong><\/p>\n\n\n\n<p>It doesn\u2019t need to have a specific variable allocated in memory.<\/p>\n\n\n\n<p>It also doesn\u2019t need a function body! It\u2019s enough for it to have<strong> just the prototype.<\/strong><\/p>\n\n\n\n<p>You might ask how is that possible?! Keyword:<strong> at the compilation stage.<\/strong><\/p>\n\n\n\n<p>This is quite funny, but <strong>compilation <\/strong>as a whole process from A to Z <strong>is divided into several stages.<\/strong> The most important ones are:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Preprocessor<\/li>\n\n\n\n<li>Compilation<\/li>\n\n\n\n<li>Linking<\/li>\n<\/ol>\n\n\n\n<p>Yes! Compilation is part of compilation! Great, right? \ud83d\ude42<\/p>\n\n\n\n<p>And it is exactly for step no. 2 that only knowledge of prototypes is needed. Why?<\/p>\n\n\n\n<p>Because this stage compiles <strong>ONLY one <\/strong>C file at a time. From one file it creates one so-called object file. Such <strong>modules<\/strong> are created. This is a single<strong> compilation unit<\/strong>.<\/p>\n\n\n\n<p>In it (in that object file) there is (speaking in a huge simplification) information that we want to use variable X in some place or function Y with arguments Z and W in such a place in the program.<\/p>\n\n\n\n<p><strong>Compilation creates <\/strong>therefore (again in a huge simplification) a <strong>map of relationships<\/strong> of what, when, how, and with what operations to do. Bare assembly <strong>without ties to addresses<\/strong> in memory.<\/p>\n\n\n\n<p>It doesn\u2019t have to know the function, but it knows that it has to be called. Now <strong>who ties<\/strong> this information together? The <strong>LINKER <\/strong>at the<strong> linking stage.<\/strong><\/p>\n\n\n\n<p>The linker at input <strong>collects all object files<\/strong> after compilation and <strong>creates a whole from them.<\/strong> It resolves these relationships of variables and functions between modules and assigns them specific locations in memory, e.g., of the microcontroller.<\/p>\n\n\n\n<p>It sees, for example, that Module1 wanted to call a function located in Module2. <strong>So it links the call with the function located in ANOTHER compilation unit.<\/strong><\/p>\n\n\n\n<p>This will be important to understand the essence of how it works. Because what does such a prototype tell the compiler?<\/p>\n\n\n\n<p><em>\u201cI have such a function and I want to use it. I don\u2019t have the body \u2013 the linker will resolve it.\u201d<\/em><\/p>\n\n\n\n<p><em>The compiler will set up the instructions, arguments on the <\/em>stack, the return from the function, and that\u2019s it. Now the linker has to connect these operations with the appropriate function in another compilation unit.<\/p>\n\n\n\n<p>And here we arrive at the fact that both the compiler and the linker will report<strong> different problems.<\/strong><\/p>\n\n\n\n<p>The <strong>compiler <\/strong>will most often tell you that <strong>it doesn\u2019t know the name of a variable or a function when they are used.<\/strong> This means that it has<strong> never seen<\/strong> the function prototype or the variable definition before. <strong>You need to inform it only about the existence (name and types).<\/strong> The function body or memory reservation for a variable may be in another compilation unit. That doesn\u2019t interest it.<\/p>\n\n\n\n<p>What does the <strong>linker<\/strong> most often report? That <strong>it can\u2019t resolve a reference.<\/strong> Such a situation will occur if in one compilation unit we inform with a prototype about the existence of a function whose\u2026 <strong>body won\u2019t exist anywhere else<\/strong> (in other compilation units). The linker didn\u2019t resolve the reference and returned an error.<\/p>\n\n\n\n<p>These are two<strong> completely different<\/strong> messages and you have to approach them differently.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p>I got a bit carried away, and I still feel I haven\u2019t said everything\u2026 Let me know if you\u2019d like something in a longer and more expanded form.<\/p>\n\n\n\n<p>We didn\u2019t do, for example, a practice session\u2014i.e., how it should actually look, e.g., in an online compiler. In text form it may be hard to carry out. Maybe you\u2019d prefer learning in video form? In that case, I have a certain proposal \ud83d\ude42<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Do you want to learn the C language with microcontrollers in mind?<\/h2>\n\n\n\n<p>I created a course dedicated to microcontrollers (the course is conducted in Polish). <strong>I teach C from the basics there. Everything I discussed in this post (and much, much more) is included in the course curriculum.<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/cdlamikrokontrolerow.pl\/webinar\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"500\" height=\"99\" src=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2021\/10\/Kurs-C-dla-embedded-logo-500px.jpg\" alt=\"\" class=\"wp-image-1967\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2021\/10\/Kurs-C-dla-embedded-logo-500px.jpg 500w, https:\/\/msalamon.pl\/wp-content\/uploads\/2021\/10\/Kurs-C-dla-embedded-logo-500px-300x59.jpg 300w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/a><\/figure>\n\n\n\n<p><strong>I\u2019ve gathered my experience from several years of embedded programming<\/strong> and I want to pass on the best knowledge possible. I participated in various projects: on my own, a start-up, a medium-sized company, and a huge corporation.<\/p>\n\n\n\n<p>Apart from the basics and syntax, <strong>I share a ton of good practices.<\/strong> I weave this in between explaining subsequent aspects of the C language.<\/p>\n\n\n\n<p>An additional advantage is also that I show <strong>how to manage a project well.<\/strong> I\u2019ll show you how to deal with building abstraction layers. We\u2019ll use <strong>structures, pointers, and callbacks.<\/strong> And of course splitting into files. It helps a lot.<\/p>\n\n\n\n<p>Such separated layers are much easier to \u043f\u0435\u0440\u0435\u043d\u043e\u0441 between projects, and even between different families of microcontrollers.<\/p>\n\n\n\n<p><strong> <strong>Join the waiting list for the course and start learning together with the materials I\u2019ve prepared. After signing up, you will receive weekly emails about the C language (the newsletter is conducted in Polish): <a href=\"https:\/\/cdlamikrokontrolerow.pl\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/cdlamikrokontrolerow.pl<\/a><\/strong> <\/strong><\/p>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;4163&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;0&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;0&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;0&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;0\\\/5 - (0 votes)&quot;,&quot;size&quot;:&quot;24&quot;,&quot;title&quot;:&quot;Project File Structure in C \\u0026#8211; Introduction&quot;,&quot;width&quot;:&quot;0&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} - ({count} {votes})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 0px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 19.2px;\">\n            <span class=\"kksr-muted\"><\/span>\n    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>I\u2019d like to make an introduction to splitting a project into files in the C language. We also need this in order to understand what a module or a compilation unit is. A good understanding of the concept of a \u201ccompilation unit\u201d will make it so that later you\u2019ll be [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3739,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[160],"tags":[176,174],"class_list":["post-4163","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-stm32","tag-programming","tag-stm32"],"_links":{"self":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts\/4163","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/comments?post=4163"}],"version-history":[{"count":4,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts\/4163\/revisions"}],"predecessor-version":[{"id":4167,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts\/4163\/revisions\/4167"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/media\/3739"}],"wp:attachment":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/media?parent=4163"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/categories?post=4163"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/tags?post=4163"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}