{"id":8079,"date":"2023-01-05T12:09:12","date_gmt":"2023-01-05T11:09:12","guid":{"rendered":"https:\/\/playembedded.org\/?p=8079"},"modified":"2024-01-17T09:41:37","modified_gmt":"2024-01-17T08:41:37","slug":"demystifying-c-types","status":"publish","type":"post","link":"https:\/\/playembedded.org\/blog\/demystifying-c-types\/","title":{"rendered":"Demystifying C: Types"},"content":{"rendered":"<h2 class=\"wp-block-heading level_1\" id=\"1_Introduction\">Introduction<\/h2>\n\n\n\n<p>In this article, we will give an exhaustive overview of types and the associated keywords that often generate confusion while working with C.<\/p>\n\n\n\n<p>C is a rigorous language when it comes to variables. Through its syntax, it requires you to specify how big need to be the associated memory area, in which memory section the variable will be stored, what is its scope and what kind of operation and function can operate on it. This is achieved by specifying the type of the variable when declaring it. Optionally a type can be accompanied by specific keywords that will influence the behavior of the compiler.<\/p>\n\n\n\n<p>But let&rsquo;s start from the basics.<\/p>\n\n\n\n<h2 class=\"wp-block-heading level_1\" id=\"2_Primitive_types\">Primitive types<\/h2>\n\n\n\n<p>C offers four built-in data types also known as <strong>primitive<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><em><strong>char<\/strong><\/em>, the smallest addressable type with a size of 1 Byte. While a char is de-facto an integer number, it is used to represent a character. This is done by assigning each character to a number from 0 to 127 (see <a rel=\"noreferrer noopener\" href=\"https:\/\/en.wikipedia.org\/wiki\/ASCII#Control_code_chart\" data-type=\"URL\" data-id=\"https:\/\/en.wikipedia.org\/wiki\/ASCII#Control_code_chart\" target=\"_blank\">ASCII table<\/a>)<\/li>\n\n\n\n<li><strong><em>int<\/em><\/strong>, an integer number type<\/li>\n\n\n\n<li><em><strong>float<\/strong><\/em>, real <em>floating-point<\/em> type, usually referred to as an IEEE 754 single-precision floating-point type. In a nutshell, a float uses scientific notation to have a very wide range (see <a rel=\"noreferrer noopener\" href=\"https:\/\/en.wikipedia.org\/wiki\/Floating-point_arithmetic\" target=\"_blank\">Floating-point arithmetic<\/a>)<\/li>\n\n\n\n<li><strong><em>double<\/em><\/strong>, real floating-point type, usually referred to as an IEEE 754 double-precision floating-point type. It has double the size of a float, hence a wider range.<\/li>\n<\/ul>\n\n\n\n<p>As an example declaring a variable of type char and assigning its value to &lsquo;a&rsquo; looks like<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">char myvar = 'a';<\/pre>\n\n\n\n<p>As said, the type specifies how many bits need to be reserved in memory and allocated when a variable is declared.<\/p>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table><thead><tr><th>Type<\/th><th>Size<\/th><th>Range<\/th><\/tr><\/thead><tbody><tr><td>char<\/td><td>8 bit<\/td><td>depends on compiler options<\/td><\/tr><tr><td>int<\/td><td>depends on the compiler and architecture, influenced by modifiers<\/td><td>depends<\/td><\/tr><tr><td>float<\/td><td>32 bit<\/td><td>1.2E-38 to 3.4E+38<\/td><\/tr><tr><td>double<\/td><td>64 bit<\/td><td>2.3E-308 to 1.7E+308<\/td><\/tr><\/tbody><\/table><figcaption class=\"wp-element-caption\">Size and range of Primitives in C<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading level_1\" id=\"3_Type_modifiers\">Type modifiers<\/h2>\n\n\n\n<p>The primitives can be combined with four special C Keywords knowns as <strong>modifiers<\/strong> that will directly influence the size and range of the variable<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><em><strong>signed<\/strong><\/em>\/<em><strong>unsigned<\/strong><\/em>, to specify if the type comes with the sign. This modifier directly impacts the range too.<\/li>\n\n\n\n<li><strong><em>long<\/em><\/strong>\/<strong><em>short<\/em><\/strong>, mainly used with integers to change the size of it.<\/li>\n<\/ul>\n\n\n\n<p>The modifier is added during the declaration of a variable, typically in front of the type. While many compilers don&rsquo;t care about the order, only certain combinations make sense. The following combinations are possible<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/* Char with no explicit signedness. *\/\nchar myvar;\n\n\/* Char with sign. *\/\nsigned char myvar;\n\n\/* Char without sign. *\/\nunsigned char myvar;\n\n\/* Short integer with sign. *\/\nshort myvar;\nshort int myvar;\nsigned short myvar;\nsigned short int myvar;\n\n\/* Short integer without sign. *\/\nunsigned short myvar;\nunsigned short int myvar;\n\n\/* Integer with sign. *\/\nint myvar;\nsigned myvar;\nsigned int myvar;\n\n\/* Integer without sign. *\/\nunsigned myvar;\nunsigned int myvar;\n\n\/* Long integer with sign. *\/\nlong myvar;\nlong int myvar;\nsigned long myvar;\nsigned long int myvar;\n\n\/* Long integer without sign. *\/\nunsigned long myvar;\nunsigned long int myvar;\n\n\/* Very Long integer with sign. *\/\nlong long myvar;\nlong long int myvar;\nsigned long long myvar;\nsigned long long int myvar;\n\n\/* Very long integer without sign. *\/\nunsigned long long myvar;\nunsigned long long int myvar;<\/pre>\n\n\n\n<p>The following table explains how the size and range are influenced by these modifiers.<\/p>\n\n\n\n<p>Note that if no sign modifier is applied to an integer, the compiler assumes <strong><em>signed <\/em><\/strong>as default. Furthermore, the default signedness of a char depends on some compiler options. Finally, close attention needs to be paid to int and long int whose size and range depend on the compiler, architecture, or OS in use.<\/p>\n\n\n\n<h2 class=\"wp-block-heading level_1\" id=\"4_Portable_Fixed_Width_Integer\">Portable Fixed-Width Integer<\/h2>\n\n\n\n<p>This problem of not well-defined integers is well known and has been later addressed with the <strong>Portable Fixed-Width Integer<\/strong> introduced with C-99<\/p>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table><thead><tr><th>Type<\/th><th>Description<\/th><th>Size<\/th><th>Range<\/th><\/tr><\/thead><tbody><tr><td>int8_t<\/td><td>8-bit integer with sign<\/td><td>1 byte<\/td><td>-128 to 127<\/td><\/tr><tr><td>uint8_t<\/td><td>8-bit integer without sign<\/td><td>1 byte<\/td><td>0 to 255<\/td><\/tr><tr><td>int16_t<\/td><td>16-bit integer with sign<\/td><td>2 byte<\/td><td>-2<sup>15<\/sup> to 2<sup>15<\/sup>-1<\/td><\/tr><tr><td>uint16_t<\/td><td>16-bit integer without sign<\/td><td>2 byte<\/td><td>0 to 2<sup>16<\/sup>-1<\/td><\/tr><tr><td>int32_t<\/td><td>32-bit integer with sign<\/td><td>4 byte<\/td><td>-2<sup>31<\/sup> to 2<sup>31<\/sup>-1<\/td><\/tr><tr><td>uint32_t<\/td><td>32-bit integer without sign<\/td><td>4 byte<\/td><td>0 to 2<sup>32<\/sup><\/td><\/tr><tr><td>int64_t<\/td><td>64-bit integer with sign<\/td><td>8 byte<\/td><td>-2<sup>63<\/sup> to 2<sup>63<\/sup>-1<\/td><\/tr><tr><td>uint64_t<\/td><td>64-bit integer without sign<\/td><td>8 byte<\/td><td>0 to 2<sup>64<\/sup>-1<\/td><\/tr><\/tbody><\/table><figcaption class=\"wp-element-caption\">Size and range of C-99 Portable Fixed-Width Integer<\/figcaption><\/figure>\n\n\n\n<p>For this reason, using these types is recommended when you want to keep strict control of your application as typically happens when developing firmware on embedded systems.<\/p>\n\n\n\n<h2 class=\"wp-block-heading level_1\" id=\"5_Storage_classes\">Storage classes<\/h2>\n\n\n\n<p>The storage classes are C keywords that can be used to determine the lifetime, visibility and memory location of a variable. There are 4 classes: <strong>auto<\/strong>, <strong>static<\/strong>, <strong>register<\/strong> and <strong>extern<\/strong>. Like the type modifiers, the storage class is added during the declaration of a variable, typically in front of the type.<\/p>\n\n\n\n<h3 class=\"wp-block-heading level_2\" id=\"6_auto\">auto<\/h3>\n\n\n\n<p>This is the default storage class and limits the visibility of a variable to the block where the variable is declared. A block is delimited by brackets {}. Examples of blocks are<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/* Simple block. *\/\n{\n  \/* unsigned int a = 0; would have the same effect. *\/\n  auto unsigned int a = 0;\n}\n\n\/* Nested block. *\/\n{\n  {\n    int a = 0;\n  }\n}\n\n\/* Still a block. The block is executed when main is called. *\/\nint main() {\n  int a = 0;\n}\n\n\/* Still a block. The block is executed when condition is true. *\/ \nif(condition) {\n  int a = 0;\n}\n\n\/* Still a block. The block is executed N times. *\/ \nfor(i = 0; i &lt; N; i++) {\n  int a = 0;\n}<\/pre>\n\n\n\n<p>When calling a function, some space in the <strong>Stack<\/strong> section (RAM) is automatically allocated: it is called <strong>Stack Frame<\/strong> and it contains the address of the return value of the function, the function arguments and all the automatic variables declared in the function. The Stack Frame is deallocated when the function returns. This implies that the Stack used sizes increases and reduces over the program lifetime. For this reason, the area of memory of a Stack Frame can be populated with garbage value from a precedently executed function impacting the initial value of automatic variables. With this in mind, we can state that:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>an automatic variable is a local variable that is visible only in the block in which it is declared<\/li>\n\n\n\n<li>an automatic variable cannot be declared outside of a function<\/li>\n\n\n\n<li>its initial value can be garbage so it is good practice to initialize it before using it<\/li>\n\n\n\n<li>the lifetime of an automatic variable is tied to the function in which it is declared<\/li>\n<\/ul>\n\n\n\n<p>To conclude let&rsquo;s do some examples.<\/p>\n\n\n\n<h4 class=\"wp-block-heading level_3\" id=\"7_Not_an_automatic_variable\">Not an automatic variable<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#include &lt;stdio.h&gt;\n\nauto int myvar = 3\n\nint main() {\n\n  printf(\"%d\", myvar);\n  return 0;\n}<\/pre>\n\n\n\n<p>This code will throw an error at compile time such as<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">main.c:3:10: error: file-scope declaration of &lsquo;myvar&rsquo; specifies &lsquo;auto&rsquo;\n    3 | auto int myvar = 3;<\/pre>\n\n\n\n<p>This is because the variable <code>myvar<\/code> cannot be an automatic variable as it is outside of a function. A variable outside the functions without a keyword is a global variable in C. Its lifetime is the entire application&rsquo;s lifetime and it is stored in the RAM and more precisely in the <strong>.data<\/strong> section if it is initialized or in the <strong>.BSS<\/strong> section if it is uninitialized.<\/p>\n\n\n\n<h4 class=\"wp-block-heading level_3\" id=\"8_Uninitialized_automatic_variable\">Uninitialized automatic variable<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#include &lt;stdio.h&gt;\n\nint main() {\n  int myvar;\n  printf(\"%d\", myvar);\n\n  return 0;\n}<\/pre>\n\n\n\n<p>This code will print a garbage value as the Stack Frame is not necessarily initialized to 0.<\/p>\n\n\n\n<h4 class=\"wp-block-heading level_3\" id=\"9_Automatic_variable_scope\">Automatic variable scope<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#include &lt;stdio.h&gt;\n\nint main() {\n  {\n    int myvar;\n  }\n  printf(\"%d\", myvar);\n\n  return 0;\n}<\/pre>\n\n\n\n<p>This code will return an error on the printf line at compile time as the variable <code>myvar<\/code> is not accessible outside of its block.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#include &lt;stdio.h&gt;\n\nvoid myfunction(void) {\n  int myvar = 0;\n  printf(\"%d\", myvar);\n}\n\nint main() {\n\n  myfunction();\n\n  myvar += 10;\n  printf(\"%d\", myvar);\n  return 0;\n}<\/pre>\n\n\n\n<p>This code will return also an error at compile time as the variable <code>myvar<\/code><em> <\/em>exists only in <code>myfunction<\/code><em> <\/em>and not in <code>main<\/code>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading level_3\" id=\"10_Lexical_scoping\">Lexical scoping<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#include &lt;stdio.h&gt;\n \n\/* 1. myvar declared outside of any block. *\/\nint myvar = 50;\n\nvoid myfunc(void) {\n  printf(\"%d\\r\\n\", myvar);\n}\n\nint main() {\n  \/* 2. myvar declared inside main. *\/\n  int myvar = 100;\n  {\n    \/* 3. myvar declared inside a sub-block in main. *\/\n    int myvar = 200;\n    printf(\"%d\\r\\n\", myvar);\n    myvar += 50;\n    printf(\"%d\\r\\n\", myvar);\n  }\n  printf(\"%d\\r\\n\", myvar);\n  \n  myfunc();\n  return 0;\n}<\/pre>\n\n\n\n<p>This code will compile and print out<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"> 200\n 250\n 100\n 50<\/pre>\n\n\n\n<p>It may appear weird has the three declared variables have the same name. This can actually be done, although strongly discouraged because it impacts the code readability and may be a source of confusion. <\/p>\n\n\n\n<p>In C, variables with the same name that are declared in different blocks of code are treated as separate variables. The C programming language follows the rule of <em>lexical scoping<\/em> or <em>static scoping<\/em>, which means that a local variable takes precedence over a global variable with the same name.<\/p>\n\n\n\n<p>This means that, within a block of code, if a local variable with the same name as a global variable is declared, the local variable will be used instead of the global variable. If the local variable is not used within that block of code, then the global variable will be used.<\/p>\n\n\n\n<p>In this example, we have three variables with the same name:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><code>myvar<\/code> declared outside of any block with a value of 50. This is a global variable.<\/li>\n\n\n\n<li><code>myvar<\/code> declared inside the <code>main<\/code> function with the value 100. This is a local variable to the <code>main<\/code> function.<\/li>\n\n\n\n<li><code>myvar<\/code> declared inside a sub-block within the <code>main<\/code> function with the value 200. This is a local variable to the sub-block.<\/li>\n<\/ol>\n\n\n\n<p>Within the sub-block, the local variable with the value 200 takes precedence over the other two variables, so it is used. Outside of the sub-block, the local variable with the value 100 takes precedence over the global variable with the value 50, so it is used. When <code>myfunc<\/code> is called, the global variable with the value 50 is used because it is the only variable with that name in the scope of <code>myfunc<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading level_2\" id=\"11_static\">static<\/h3>\n\n\n\n<p>This storage class instructs the compiler to keep a local variable in existence during the entire lifetime of the program. This means the variable continues to exist and keeps its value even when the function is terminated. <\/p>\n\n\n\n<p>As an automatic variable, a static one is visible only in the block where it is declared. If this variable is declared outside of any block it is visible only in the file where it is declared. It is stored in the RAM memory and more precisely in the <strong>.data<\/strong> section if it is initialized or in the <strong>.BSS<\/strong> section if it is uninitialized.<\/p>\n\n\n\n<p>Let&rsquo;s do some examples<\/p>\n\n\n\n<h4 class=\"wp-block-heading level_3\" id=\"12_An_automatic_variable_vs_a_static_variable\">An automatic variable vs a static variable<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#include &lt;stdio.h&gt;\n\nvoid myfunc(void) {\n  int auto_var = 3;\n  static int static_var = 3;\n  printf(\"The auto_var is %d, static_var is %d\\r\\n\", auto_var, static_var);\n  auto_var++;\n  static_var++;\n}\n\nint main() {\n  int count = 0;\n  for(count = 0; count &lt; 5; count++) {\n      printf(\"Iteration %d: \", count);\n      myfunc();\n  }\n  return 0;\n}<\/pre>\n\n\n\n<p>that will generate the following output<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Iteration 0: The auto_var is 3, static_var is 3\nIteration 1: The auto_var is 3, static_var is 4\nIteration 2: The auto_var is 3, static_var is 5\nIteration 3: The auto_var is 3, static_var is 6\nIteration 4: The auto_var is 3, static_var is 7<\/pre>\n\n\n\n<p>While <code>auto_var<\/code> dies and is recreated every time that <code>myfunc<\/code><em> <\/em>returns, <code>static_var<\/code><em> <\/em>survives and keeps its value. It is worth noticing that the initialization of the static variable happens only once.<\/p>\n\n\n\n<h4 class=\"wp-block-heading level_3\" id=\"13_Visibility_within_the_sheet\">Visibility within the sheet<\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#include &lt;stdio.h&gt;\n\nstatic int myvar = 0;\n\nvoid myfunc() {\n  myvar++;\n}\n\nint main() {\n\n  int count = 0;\n  for(count = 0; count &lt; 5; count++) {\n      printf(\"%d\\r\\n\", myvar);\n      myfunc();\n  }\n  return 0;\n}<\/pre>\n\n\n\n<p>In this example, <code>myvar<\/code><em> <\/em>is visible both from <code>myfunc<\/code><em> <\/em>and <code>main<\/code>. The result will be<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">0\n1\n2\n3\n4<\/pre>\n\n\n\n<h3 class=\"wp-block-heading level_2\" id=\"14_register\">register<\/h3>\n\n\n\n<p> <span style=\"font-size: revert; color: initial;\">This storage class instructs<\/span> the compiler to keep a <span style=\"font-size: revert; color: initial;\">variable in a register of the CPU. This has some implications:<\/span><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The size of the variable is tied to the size of a register<\/li>\n\n\n\n<li>It is not possible to use the &amp; operator on the variable as the register has no memory address hence is not possible to reference the variable <\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading level_2\" id=\"15_extern\">extern<\/h3>\n\n\n\n<p>This storage class instructs the compiler to access a global variable defined in some other source file. Note that the extern keyword declares the variable but does not defines it: in other words, no memory is allocated when using <code>extern<\/code> and if the variable is not defined somewhere an error is thrown.<\/p>\n\n\n\n<p>Some examples will shed light on the matter<\/p>\n\n\n\n<h4 class=\"wp-block-heading level_3\" id=\"16_Typical_extern_use_case\">Typical extern use case<\/h4>\n\n\n\n<p>In this example, we have two source files for our project.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/* main.c *\/\n\n#include &lt;stdio.h&gt;\n\nextern int myvar;\n\nint main() {\n  printf(\"myvar is %d\", myvar);\n\n  return 0;\n}<\/pre>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/* mylib.c *\/\n\nint myvar = 10;<\/pre>\n\n\n\n<p>Building this project will result in<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">myvar is 10<\/pre>\n\n\n\n<p>Note then that <code>myvar<\/code> is a global variable made accessible using the <code>extern<\/code> storage class. Note also that the variable has been defined and initialized in <code>mylib.c<\/code> and declared in <code>main.c<\/code> where it has been used<\/p>\n\n\n\n<h3 class=\"wp-block-heading level_2\" id=\"17_Summary_table\">Summary table<\/h3>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table><thead><tr><th class=\"has-text-align-center\" data-align=\"center\">Storage class<\/th><th class=\"has-text-align-center\" data-align=\"center\">Storage<\/th><th class=\"has-text-align-center\" data-align=\"center\">Default value<\/th><th class=\"has-text-align-center\" data-align=\"center\">Scope<\/th><th class=\"has-text-align-center\" data-align=\"center\">Lifetime<\/th><\/tr><\/thead><tbody><tr><td class=\"has-text-align-center\" data-align=\"center\">auto<\/td><td class=\"has-text-align-center\" data-align=\"center\">Stack frame<\/td><td class=\"has-text-align-center\" data-align=\"center\">garbage<\/td><td class=\"has-text-align-center\" data-align=\"center\">block<\/td><td class=\"has-text-align-center\" data-align=\"center\">end of block<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">static<\/td><td class=\"has-text-align-center\" data-align=\"center\">.data or .bss<\/td><td class=\"has-text-align-center\" data-align=\"center\">zero<\/td><td class=\"has-text-align-center\" data-align=\"center\">block<\/td><td class=\"has-text-align-center\" data-align=\"center\">end of program<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">register<\/td><td class=\"has-text-align-center\" data-align=\"center\">CPU register<\/td><td class=\"has-text-align-center\" data-align=\"center\">garbage<\/td><td class=\"has-text-align-center\" data-align=\"center\">block<\/td><td class=\"has-text-align-center\" data-align=\"center\">end of block<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">extern<\/td><td class=\"has-text-align-center\" data-align=\"center\">.data or .bss<\/td><td class=\"has-text-align-center\" data-align=\"center\">zero<\/td><td class=\"has-text-align-center\" data-align=\"center\">global<\/td><td class=\"has-text-align-center\" data-align=\"center\">end of program<\/td><\/tr><\/tbody><\/table><figcaption class=\"wp-element-caption\">Data storage classes in C summary<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading level_1\" id=\"18_Qualifiers\">Qualifiers<\/h2>\n\n\n\n<p>To complete the picture, C offers two type qualifiers that modify the property of a variable and allows the compiler to perform optimizations correctly:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><em><strong>const<\/strong><\/em><\/li>\n\n\n\n<li><em><strong>volatile<\/strong><\/em><\/li>\n<\/ul>\n\n\n\n<p>Like the type modifiers and the storage classes, also qualifiers are added during the declaration of a variable, typically in front of the type.<\/p>\n\n\n\n<h3 class=\"wp-block-heading level_2\" id=\"19_const\">const<\/h3>\n\n\n\n<p>This qualifier tells the compiler that a variable will be constant during the entire lifetime of the program. This opens to optimization such as moving this variable in the <strong>.ro<\/strong> session of the memory: it stands for read-only and typically it is mapped onto the Flash memory to spare RAM space.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/* This is a global constant variable. *\/\nconst int myvar = 10;\n\n\/* This is a static constant variable. *\/\nstatic const int myvar = 10;\n\nint myfunc() {\n  \/* This is an automatic constant variable. *\/\n  const int myvar = 10;\n  return myvar;\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading level_2\" id=\"20_volatile\">volatile<\/h3>\n\n\n\n<p>This qualifier tells the compiler the value of that variable can change at any time by something unrelated to the C code. The implications of such an occurrence are crucial: this tells the compiler to not do any assumption on that variable. For the purpose of shedding some light follow me in this last digression.<\/p>\n\n\n\n<p>Let us say that at a specific memory address (e.g. <code>0x40000010<\/code>) is located a 32-bit secret register that allows us to unlock some special features of our machine. To unlock these features we need to write a secret sequence onto it (e.g. <code>0x10105555<\/code>, <code>0x11105522<\/code>, <code>0xFF505050<\/code>). Keen to unlock the full potential of our machine, we will promptly write<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/* Pointer to an unsigned 32-bit. Initializing this to the memory\n   address of the register, I may use the pointer to write into\n   the register. *\/\nuint32_t * mypointer = 0x40000010;\n\nint main() {\n\n  \/* Writing the sequence. *\/\n  *mypointer = 0x10105555;\n  *mypointer = 0x11105522;\n  *mypointer = 0xFF505050;\n}<\/pre>\n\n\n\n<p>On paper, that does exactly what we said. Unfortunately, if the compiler optimizations are enabled, this may not work. The compiler sees that we are writing three values in the same memory location without doing any operation in between so it skips the first two assignments and performs only the last one.<\/p>\n\n\n\n<p>Here comes to play <code>volatile<\/code>. The following code solves the issue<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/* Pointer to a volatile unsigned 32-bit. *\/\nvolatile uint32_t * mypointer = 0x40000010;\n\nint main() {\n\n  \/* Writing the sequence. *\/\n  *mypointer = 0x10105555;\n  *mypointer = 0x11105522;\n  *mypointer = 0xFF505050;\n}<\/pre>\n\n\n\n<p>Adding the keyword volatile the compiler stops to do assumptions about the value assigned to that specific memory location. Consequently, all three assignments will be performed.<\/p>\n\n\n\n<p>This example serves well in three possible real-life scenarios:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Memory-mapped peripheral registers<\/li>\n\n\n\n<li>Global variables modified by an Interrupt Service Routine<\/li>\n\n\n\n<li>Global variables within a multi-threaded application<\/li>\n<\/ul>\n\n","protected":false},"excerpt":{"rendered":"<p>In this article, we will give an exhaustive overview of types and the associated keywords that often generate confusion while working with C.<\/p>\n","protected":false},"author":3,"featured_media":8143,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1289],"tags":[1292],"coauthors":[241],"class_list":["post-8079","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-advanced-concepts","tag-c-programming","lime"],"views":3906,"jetpack_featured_media_url":"https:\/\/playembedded.org\/blog\/wp-content\/uploads\/2023\/04\/Demistifying-C-types-PE-1.jpg","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/posts\/8079","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/comments?post=8079"}],"version-history":[{"count":0,"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/posts\/8079\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/media\/8143"}],"wp:attachment":[{"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/media?parent=8079"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/categories?post=8079"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/tags?post=8079"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/coauthors?post=8079"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}