Issue
In the C language Specification, there are constraints of minimum length of built-in types; thus, a compiler must ensure that the length of char
is at least 8 bit, int
32 bits, long long
64 bits, etc.
But, when I am implementing architecture-related parts of my kernel, I need some types that have definite lengths of 8 bits, 16 bits, 32 bits or 64 bits. With those types, I can read form or write to 8-bit and 16-bit I/O ports, or 32-bit and 64-bit registers. Are there any existing types that have assured lengths?
When I'm looking up such type definitions in Linux source code (like u32
or u64
), I found that they are defined by built-in types as:
<uapi\asm-generic\int-ll64.h>
typedef __signed__ char __s8;
typedef unsigned char __u8;
typedef __signed__ short __s16;
typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
typedef __signed__ long long __s64;
typedef unsigned long long __u64;
and
<linu\asm-generic\int-ll64.h>
typedef __s8 s8;
typedef __u8 u8;
typedef __s16 s16;
typedef __u16 u16;
typedef __s32 s32;
typedef __u32 u32;
typedef __s64 s64;
typedef __u64 u64;
The kernel use such types to define some other types that look like they have definite length:
#ifdef CONFIG_PHYS_ADDR_T_64BIT
typedef u64 phys_addr_t;
#else
typedef u32 phys_addr_t;
#endif
Or to say, when compiling code for specific architecture, lengths of those built-in types can be assured? Or does the Linux MakeFile use some flags and compile options to make type lengths fixed?
Solution
The C Standard specifies the "stdint.h" header/library file (which you can incorporate into your code with a line like #include <stdint.h>
) that provdes definitions for 'fixed width' integer types.
From this Draft C11 Standard:
7.20 Integer types
<stdint.h>
1 The header
<stdint.h>
declares sets of integer types having specified widths, and defines corresponding sets of macros. It also defines macros that specify limits of integer types corresponding to types defined in other standard headers.
Using this header, you have access to types like int64_t
and uint8_t
; from the same Draft Standard section (bold italic emphasis in §3 mine):
7.20.1.1 Exact-width integer types
1 The typedef name
intN_t
designates a signed integer type with width N, no padding bits, and a two’s complement representation. Thus,int8_t
denotes such a signed integer type with a width of exactly 8 bits.
2 The typedef nameuintN_t
designates an unsigned integer type with width N, no padding bits, Thus, uint24_t denotes such an unsigned integer type with a width of exactly 24 bits.
3 These types are optional. However, if an implementation provides integer types with widths of 8, 16, 32, or 64 bits, no padding bits, and (for the signed types) that have a two’s complement representation, it shall define the corresponding typedef names.
Note: This "stdint.h" header is also specified in the same section of the C17 Standard and in a similar one (§7.22) in C23. It has been part of the Standard since at least C99 (§7.18).
Answered By - Adrian Mole Answer Checked By - David Goodson (WPSolving Volunteer)