difference between int_fast8_t and int_fast16_t

Viewed 260

I'm a beginner to embedded system and I saw in the header file that int_fast8_t/int_fast16_t/int_fast32_t are all just signed int. So is there any difference between them? Or are they basically the same and even you assigned 32 bits to int_fast8_t it will still store the 32 bits instead of making it 8 bits?

    /* fastest minimum-width signed integer types */
typedef    signed            int    int_fast8_t;
typedef    signed            int    int_fast16_t;
typedef    signed            int    int_fast32_t;
typedef    signed        __INT64    int_fast64_t;
1 Answers

That is how a specific implementation defines them. The standard requires an int_fast8_t to be at least 8 bits. And the purpose of them is that the implementation should use the fastest of them, but there are no strict requirements about this or about how to measure it.

C11 standard 7.20.1.3 says

1 Each of the following types designates an integer type that is usually fastest(262) to operate with among all integer types that have at least the specified width.

2 The typedef name int_fastN_t designates the fastest signed integer type with a width of at least N . The typedef name uint_fastN_t designates the fastest unsigned integer type with a width of at least N .

3 The following types are required:

    int_fast8_t                                    uint_fast8_t
    int_fast16_t                                   uint_fast16_t
    int_fast32_t                                   uint_fast32_t
    int_fast64_t                                   uint_fast64_t

All other types of this form are optional.

The note linked says:

  1. The designated type is not guaranteed to be fastest for all purposes; if the implementation has no clear grounds for choosing one type over another, it will simply pick some integer type satisfying the signedness and width requirements.

Typically, the "fast" variables are defined to be the native size for the target processor, provided it is at least as big as the specified size. Note that it depends on the situation which is faster. When you have a single variable that you do operations on, it's typically best with the native size, but on large arrays, you instead typically want the smallest type that fits your needs, because the larger an array is in raw bytes, the worse it is for the cache.

For instance, Take the Open Watcom for DOS. There you have this:

typedef signed   int       int_fast8_t;
typedef signed   int       int_fast16_t;
typedef signed   long      int_fast32_t;
typedef signed   long long int_fast64_t;

Notice that it's a difference between the 32 bit and 16 bit, which it is not in your example.

On my gcc implementation I have this:

typedef unsigned char uint_fast8_t;
typedef unsigned long int uint_fast16_t;
typedef unsigned long int uint_fast32_t;
typedef unsigned long int uint_fast64_t;

AFIK int8_t will behave exactly like int_fast8_t in almost all situations. But there are some situations where you might want to be careful. Look at this program:

#include <stdio.h>
#include <stdint.h>

int main(void) {
    int_fast16_t array[] = { 12345,23456,34567 };
    int16_t *ptr = array;
    for(int i=0; i<3; i++) {
        printf("%d %d\n", ptr[i], array[i]);
    }
}

It gives me this warning:

$ gcc main.c 
main.c: In function ‘main’:
main.c:6:20: warning: initialization of ‘int16_t *’ {aka ‘short int *’} from incompatible pointer type ‘int_fast16_t *’ {aka ‘long int *’} [-Wincompatible-pointer-types]
    6 |     int16_t *ptr = array;
      |                    ^~~~~

And prints:

$ ./a.out 
12345 12345
0 23456
0 34567

There are basically three categories of these types:

  1. Exact width
  2. Minimum width
  3. Fastest minimum width

Exact width has to be exact, but the two others have the same requirements but different purposes.

In an embedded system, I'd choose exact width for arrays and fastest (or simply just int or long) for regular variables. I cannot really see a good use for minimum width if exact width exists, except for portability. Here I want t point out that minimum and fastest are required by the standard, but exact width are not. Most systems do support exact width. So unless you want 100% portability or know for a fact that you need to compile the code on a machine that does not support it, I'd always prefer exact width over minimum width.

Related