Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”

This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.

See this topic a lot of people will be confused, what is there to say about data types, isn’t this the basis of programming? Anyone who can write code must be familiar with data types, char,int,float,double, all of which are used hundreds of times a day. Everyone see officer don’t worry, and listen to me slowly.

For upper computer development, there is basically no special attention to the data type, except that the data length of 32-bit system and 64-bit system is not the same. It is this data length problem, for the development of single-chip computer, is crucial. Because microcontroller has 8 bits, 16 bits, 32 bits. If you don’t pay attention to the data type, if you don’t pay attention to the length of the data, when you write code, it’s very easy to overflow the data and cause bugs in your program, and it’s very hard to see why.

If you are familiar with the development of STM32 microcontroller, when you see the official routine, the data type used is often redefined, and there are few direct use of the original data type, such as GPIOIO port Settings.

This variable is of type uint16_t. Check out the definition of this data type.

It turns out that this is giving an unsigned short int a new name. A lot of people don’t understand why officials like to do this when they can just use it.

The same STM8 microcontroller official database used data type, is also a new name.

The Uint16_t also gives the unsigned short type a new name.

So why do we do this? Is it too much trouble? Usually write their own procedures, often are directly using the default name of the data type, can still be used normally, there is no problem. But why do officials have to redefine data types once again?

This is simply a matter of the big picture, because officials have a bigger picture than we do. Individuals may face only a few platforms and a few microcontrollers. And the official face is a plurality of platforms and a variety of microcontroller, which has to consider the data compatibility problem. For example, the algorithm on the 32-bit microcontroller is transplanted to the 8-bit microcontroller. After the code runs, data overflow is everywhere. If you have to change the data type of a variable one by one, do you, as a developer, crash? Crazy or not?

So in order to solve this problem, they rename the data type on each platform, and if they need to change platforms, they just replace the header file that they rename.

As can be seen from the above comparison, the left side is a 32-bit microcontroller, and the right side is an 8-bit microcontroller. In 32-bit microcontroller int is 32 bits, and in 8-bit microcontroller long is 32 bits. So int variables in the 32-bit microcontroller, if directly transplanted to the 8-bit microcontroller, then there will certainly be data overflow problems.

So if you use the new variable type uint32_t after the rename, regardless of 8 bit and 32 bit microcontroller, the data will be 32 bits, so through the redefinition of data type, to avoid, the same data type, in different platforms the length of the inconsistent problem.

Let’s actually test how long different types of data are on different platforms.

8-bit microcontroller

The sizeof function is used to calculate the number of bits of the data type, which is then printed through the serial port.

32 single chip microcomputer

Also, sizeof is used to calculate the number of bits of the data type, which is then printed through the serial port.

The printf() function uses %zd to match the type returned by sizeof(). If the compiler does not support this type, use %u or %lu instead.

Next, on a computer, using a C++ compiler, test the length of data types on both 32-bit and 64-bit systems.

Win32

Set the compiler to 32 bits

The output is

win64

Set the compiler to 64 bits

The output is:

Comparison of bytes for different platform data types

As can be seen from the table, 8-bit and 32-bit system data type length difference is relatively large, in the use of microcontroller development, to pay special attention to this point.

If you are not sure whether the data exceeds the range when developing the microcontroller, you can directly view the range of data values in the header file of the data type declaration.

8 bit single chip microcomputer data value range

32 bit microcontroller data value range

/ * 7.18.2.1 * /

    /* minimum values of exact-width signed integer types */
#define INT8_MIN                   -128
#define INT16_MIN                -32768
#define INT32_MIN          (~0x7fffffff)   /* -2147483648 is unsigned */
#define INT64_MIN  __INT64_C(~0x7fffffffffffffff) /* -9223372036854775808 is unsigned */

    /* maximum values of exact-width signed integer types */
#define INT8_MAX                    127
#define INT16_MAX                 32767
#define INT32_MAX            2147483647
#define INT64_MAX  __INT64_C(9223372036854775807)

    /* maximum values of exact-width unsigned integer types */
#define UINT8_MAX                   255
#define UINT16_MAX                65535
#define UINT32_MAX           4294967295u
#define UINT64_MAX __UINT64_C(18446744073709551615)

    / * 7.18.2.2 * /

    /* minimum values of minimum-width signed integer types */
#define INT_LEAST8_MIN                   -128
#define INT_LEAST16_MIN                -32768
#define INT_LEAST32_MIN          (~0x7fffffff)
#define INT_LEAST64_MIN  __INT64_C(~0x7fffffffffffffff)

    /* maximum values of minimum-width signed integer types */
#define INT_LEAST8_MAX                    127
#define INT_LEAST16_MAX                 32767
#define INT_LEAST32_MAX            2147483647
#define INT_LEAST64_MAX  __INT64_C(9223372036854775807)

    /* maximum values of minimum-width unsigned integer types */
#define UINT_LEAST8_MAX                   255
#define UINT_LEAST16_MAX                65535
#define UINT_LEAST32_MAX           4294967295u
#define UINT_LEAST64_MAX __UINT64_C(18446744073709551615)

    / * 7.18.2.3 * /

    /* minimum values of fastest minimum-width signed integer types */
#define INT_FAST8_MIN           (~0x7fffffff)
#define INT_FAST16_MIN          (~0x7fffffff)
#define INT_FAST32_MIN          (~0x7fffffff)
#define INT_FAST64_MIN  __INT64_C(~0x7fffffffffffffff)

    /* maximum values of fastest minimum-width signed integer types */
#define INT_FAST8_MAX             2147483647
#define INT_FAST16_MAX            2147483647
#define INT_FAST32_MAX            2147483647
#define INT_FAST64_MAX  __INT64_C(9223372036854775807)

    /* maximum values of fastest minimum-width unsigned integer types */
#define UINT_FAST8_MAX            4294967295u
#define UINT_FAST16_MAX           4294967295u
#define UINT_FAST32_MAX           4294967295u
#define UINT_FAST64_MAX __UINT64_C(18446744073709551615)

    / * 7.18.2.4 * /

    /* minimum value of pointer-holding signed integer type */
#if __sizeof_ptr == 8
#define INTPTR_MIN INT64_MIN
#else
#define INTPTR_MIN INT32_MIN
#endif

    /* maximum value of pointer-holding signed integer type */
#if __sizeof_ptr == 8
#define INTPTR_MAX INT64_MAX
#else
#define INTPTR_MAX INT32_MAX
#endif

    /* maximum value of pointer-holding unsigned integer type */
#if __sizeof_ptr == 8
#define UINTPTR_MAX UINT64_MAX
#else
#define UINTPTR_MAX UINT32_MAX
#endif

    / * 7.18.2.5 * /

    /* minimum value of greatest-width signed integer type */
#define INTMAX_MIN  __ESCAPE__(~0x7fffffffffffffffll)

    /* maximum value of greatest-width signed integer type */
#define INTMAX_MAX  __ESCAPE__(9223372036854775807ll)

    /* maximum value of greatest-width unsigned integer type */
#define UINTMAX_MAX __ESCAPE__(18446744073709551615ull)

    / * 7.18.3 * /

    /* limits of ptrdiff_t */
#if __sizeof_ptr == 8
#define PTRDIFF_MIN INT64_MIN
#define PTRDIFF_MAX INT64_MAX
#else
#define PTRDIFF_MIN INT32_MIN
#define PTRDIFF_MAX INT32_MAX
#endif

    /* limits of sig_atomic_t */
#define SIG_ATOMIC_MIN (~0x7fffffff)
#define SIG_ATOMIC_MAX   2147483647

    /* limit of size_t */
#if __sizeof_ptr == 8
#define SIZE_MAX UINT64_MAX
#else
#define SIZE_MAX UINT32_MAX
#endif

    /* limits of wchar_t */
    /* NB we have to undef and redef because they're defined in both * stdint.h and wchar.h */
#undef WCHAR_MIN
#undef WCHAR_MAX

#if defined(__WCHAR32) || (defined(__ARM_SIZEOF_WCHAR_T) && __ARM_SIZEOF_WCHAR_T == 4)
  #define WCHAR_MIN   0
  #define WCHAR_MAX   0xffffffffU
#else
  #define WCHAR_MIN   0
  #define WCHAR_MAX   65535
#endif

    /* limits of wint_t */
#define WINT_MIN (~0x7fffffff)
#define WINT_MAX 2147483647

Copy the code

The length of data on different systems certainly varies, but isn’t the exact scope of the data type specified? No, the C specification only specifies the minimum range of each data type.

Int — The basic data type given by the system. The int type must be at least 16 bits.

Short or short int — The largest short integer is less than or equal to the largest int integer. The short type has at least 16 bits.

Long or long int — Is greater than or equal to the largest int. The long type has at least 32 bits.

Long long or long long int — The representable integer of this type is greater than or equal to the largest integer of type long. Long The value of long must be at least 64 bits.