Microcontroller Embedded C Programming Lecture 77| Importance of stdint.h

 

Importance of <stdint.h>

 

 

In this article, let’s learn about the importance of <stdint.h>. <stdint.h> is one of the standard library header file.

Figure 1. Importance of stdint.h
Figure 1. Importance of stdint.h

 

Let’s say you have written a ‘C’ program, keeping in mind certain data types and its associated sizes. Now, let’s say tomorrow you change the compiler; when you change the compiler, the size of the data type may differ.

So, the code may compile fine, but it may be buggy because the new compiler uses different sizes for the data types you have used in the program. That means you will face portability issues with your code. So, there will not be a problem when you use your compiler, but if the same code is compiled using another compiler, there’s a possibility that the code may become buggy, and it will cause problems.

Importance of stdint.h
Figure 2. Data type size and compiler

 

When you write a ‘C’ program, you should give attention to all these details. There is a possibility of a portability issue in your ‘C’ code due to the selection of data types. 

 

Let’s discuss portability issues in “C” programming code due to the “size of data types”. 

Portability Issues in “C” programming code due to “size of data types”

  • In ‘C’ programming language, the most commonly used data types “int” and “long” cause portability issues.
  • The reason is that the storage size for ‘int’, ‘long’ type variable is not defined within the C standard(C90 or C99). 
  • The compiler vendors have the choice to define the storage size for the variable depending solely on hardware capabilities of the target platform, with respect to the minimum widths defined by the standard.

The standard only talks about minimum and maximum values. So, it doesn’t talk about fixing a certain amount of size for ‘int’ or ‘long’. 

 

Importance of stdint.h
Figure 3. Integer Data Types

 

For example, in the xc8 compiler, why would  xc8 compiler designers have selected 2 bytes for an int data type?  

The reason may be, According to the compiler designer keeping the size of the “int” type variable as 2 bytes will be the most efficient for data manipulation considering the underlying architecture of the PIC 8-bit microcontrollers. So, that may be the reason for that, and for ARM, it may not be true. That’s why ARM compiler designers have selected “int” as 4 bytes because that would give more speed and code size benefits. 

 

Now, let’s take a look at the code snippet.

Importance of stdint.h
Figure 4. Code snippet

 

Here, there is a variable called count, and its data type is unsigned int. And there is one conditional statement, that is If. If(count>65,536), so inside the flower brackets(Do this task), that task will be done. 

If you check this If(count>65,536) code, this code will cause portability issues, so when you change the compiler. 

 

Here, let’s say I use one compiler. I would call it compiler A, and the compiler treats the count variable as 4 bytes. When this count variable is of 4 bytes, then this If(count>65,536) code will work fine, no problem. 

And when I use this If(count>65,536) code under compiler B and let’s say if compiler B treats unsigned int as 2 bytes, then this(Do this task) task will never be executed. Because the maximum value for count is 65,535, and if you further increment this, the value goes back to 0 and starts over again.

That’s why this code will become buggy on compiler B if it uses 2 bytes for the unsigned int. So, to get rid of these kinds of problems, you must stop using these standard data type names. So, instead, use the data type alias names given by the header file stdint.h.

 

stdint.h

  • The standard library header file stdint.h defines fixed-width integers using alias data types for the standard data types available in ‘C’.
  • A fixed-width integer data type is an aliased data type that is based on the exact number of bits required to store the data.

 

For example, int8_t is an alias name for 8 bits signed data type.

What is the 8 bits signed data type in ‘C’?

It is a signed char or char. So, instead of using char, use int8_t. int8_t is actually an aliased name for the standard data type.

Figure 5. Example
Figure 5. Example

 

Instead of using unsigned char, use uint8_t. Where ‘u’ stands for unsigned. So, all these are aliased data type names for the standard data types managed by the stdint.h. How is it managed? you need not to worry about that. That will be resolved by the stdint.h. So, if you want, you can open and check the stdint.h file.  

 

Importance of stdint.h
Figure 6. Code snippet

 

So, if I use uint32_t instead of unsigned int, here it doesn’t matter under which compiler this code compiles; the compiler will always reserve 32 bits for the variable by using a suitable standard data type. So, that is guaranteed. That’s why you need not to worry about portability issues. 

 

Now, if you want to locate stdint.h or any standard library header file, you have to open the toolchain installation folder.

For example, I have a Windows 64-bit machine, and if I want to compile a ‘C’ program for my PC, I use a MinGW 64-bit toolchain. That is installed in the MinGW folder. If I go there, I will find the include folder. In the include folder, you see all standard library include files, as shown in Figure 7.

Importance of stdint.h
Figure 7. standard library include files

 

Open stdint.h file.

Importance of stdint.h
Figure 8. stdint.h file

 

Figure 8 shows a stdint.h file. Here int8_t, uint8_t, int16_t, uint16_t, like that, these are the aliased names you’ll use in your program. Signed char, unsigned char, short, unsigned short, int, unsigned, long long, unsigned long long are the aliased to standard data type names. 

How is it aliased?

It is compiler dependent. Different compilers issue different stdint.h. So, the stdint.h contents will not be the same across different compilers.

 

And the bin folder usually contains all the binaries(as shown in Figure 9), which are used during your code compilation.

Importance of stdint.h
Figure 9. bin folder

 

Let’s check the cross-compilation toolchain. Now let me check the cross-compilation toolchain for PIC microcontrollers. So, that also I have installed you can watch here.

For example, I have a Microchip folder. Here are xc8 and xc32 compilers. These are used for code generation for PIC8 and PIC32 microcontrollers.

Importance of stdint.h
Figure 10. Microchip folder

 

Open the xc8 folder; if you go inside the bin folder, you see the xc8.exe application. So, this is a compiler xc8. 

Figure 11. xc8 compiler
Figure 11. xc8 compiler

 

And in the xc8 folder, you will find a folder called pic. Here, go to the include folder(here you will find different standards); let’s go inside c99, and here you will find all the standard library header files, as shown in Figure 12.

Figure 12. Standard library header files
Figure 12. Standard library header files

 

Open the stdint.h file. So, you can see that the content of this file is different compared to the earlier one(Figure 8). That is for MinGW, this is for xc8, so here the implementation will be different. But you still get the same aliased names like int8_t, int16_t, int32_t, uint8_t,uint16_t, etc.

Importance of stdint.h
Figure 13. Stdint.h file

 

Let’s check the cross-toolchain for our STM32 microcontroller, which is based on the ARM processor installed here in the ST folder. Go to the STM32CubeIDE folder, and go to Plugins. So, let’s open the gnu-arm-embedded toolchain here, as shown in Figure 14.

Figure 14. Inside Plugins folder
Figure 14. Inside Plugins folder

 

And then go to tools, arm-none-eabi, and include folder. Open the include folder; here, you will find all the standard library header files, as shown in Figure 15.

Figure 15. Standard library header files
Figure 15. Standard library header files

 

Let’s open the stdint.h. The implementation may be different, but as I said, you will still see various alias names(Figure 16).

Figure 16. Stdint.h file
Figure 16. Stdint.h file

 

I would like to introduce some of the useful stdint.h alias names apart from what I mentioned before like int8, uint8, int32, uint32, etc. 

 

Some useful stdint.h aliases while programming

uintmax_t: defines the largest fixed-width unsigned integer possible on the system. So, you need not worry whether it is 16 or 32, or 64 bits; just use uintmax_t.

intmax_t: defines the largest fixed-width signed integer possible on the system.

uintptr_t: defines an unsigned integer type that is wide enough to store the value of a pointer. For example, for our 64-bit machine, the size of the pointer is 64 bits(8 bytes). So, when you are coding for some unknown architecture like PIC architecture or ARM architecture, you need not worry about the pointer size, so you just use uintptr_t.

 

From this article onwards, we will be using the stdint.h header file and its various alias names, and in the following article, I will cover operators in ‘C

 

FastBit Embedded Brain Academy Courses

Click here: https://fastbitlab.com/course1

 

FastBitLab

The FastBit Embedded Brain Academy uses the power of internet to bring the online courses related to the field of embedded system programming, Real time operating system, Embedded Linux systems, etc at your finger tip with very low cost. Backed with strong experience of industry, we have produced lots of courses with the customer enrolment over 3000+ across 100+ countries.