C语言小知识---数据类型

Posted 嵌入式@hxydj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言小知识---数据类型相关的知识,希望对你有一定的参考价值。

  看到这个题目好多人肯定会迷惑,数据类型有什么可说的,这不是编程的基础吗?凡是会写代码的肯定都熟悉数据类型,不就是char,int,float,double这些每天都用成百上千次的的类型吗?各位看官切莫着急,且听我慢慢道来。

  对于上位机开发来说,数据类型基本没有什么特别注意的,无非就是32位系统和64位系统的数据长度不一样。正是这个数据长度的问题,对于单片机开发来说,却是至关重要的。因为单片机有8位、16位、32位。如果不注意数据类型,不注意数据长度,那么在编写代码的时候,很容易就会造成数据溢出,导致程序出现bug,而且还很难发现原因。

  如果熟悉stm32单片机开发的同学,看官方的例程时,使用的数据类型往往都是重新定义过的类型,很少有直接使用原始数据类型的,比如GPIOIO口设置。


这个变量的类型为uint16_t,查看这个数据类型的定义。

发现这个是给 unsigned short int 重新起了一个名字。好多人不明白,为什么官方都喜欢这样做,明明可以直接使用,为什么还要换个名字。

同样STM8单片机官方库里面使用的数据类型,也是重新起了一个名字。

这个uint16_t也是给 unsigned short 类型重新起了一个名字。

  那么为什么要这样做吗?不嫌麻烦吗?自己平时写程序的时候,往往都是直接使用数据类型的默认名,也依然可以正常使用,没什么问题。但是官方为什么一定要重新定义一次数据类型呢?

  这个说白了就是大局观的问题,因为官方比我们个人更具有大局观。个人面对的可能也只有几个平台和几款单片机。而官方面对的是多个平台和多种单片机的,这就不得不考虑数据兼容问题了。比如在32位单片机上的算法移植到8位单片机上,代码运行起来后,到处都是数据溢出。要挨个去修改变量的数据类型,那么这时候,作为开发者来说,奔溃不奔溃?抓狂不抓狂?

  所以为了解决这个问题,官方就会在每个平台下,给数据类型,重新命名一次,如果需要更换平台,那么只需要替换这个数据重命名的头文件即可。

  通过上面的对比可以看出,左边是32位单片机,右边是8位单片机。在32位单片机中int是32位,而在8位单片机中long 才是32位。那么在32位单片机上的int型变量,如果直接移植到8位单片机上的话,那么肯定就会出现数据溢出的问题。

  那么如果使用了重命名后的新变量类型 uint32_t ,不论在8位和32位的单片机上,这个数据都会是32位,这样通过数据类型的重定义,就避免了,同样的数据类型,在不同平台上长度不一致的问题。

  下面就实际检验一下不同平台上,不同类型的数据长度到底是多少。

8位单片机


通过sizeof函数计算出数据类型的位数,然后通过串口打印出来。

32单片机

同样通过sizeof函数计算出数据类型的位数,然后通过串口打印出来。

这里使用printf()函数打印的时候,使用%zd,来匹配sizeof()函数返回的数据类型,如果编译器不支持这个类型,可以使用%u或者%lu来代替。

接下来在电脑上,使用C++编译器,测试32位和64位系统中数据类型的长度。

Win32

将编译器设置为32位

输出结果为

win64

将编译器设置为64位

输出结果为:

不同平台数据类型所占字节对比

通过表格可以看出,8位和32位的系统的数据类型长度差别还是比较大的,在使用单片机开发的时候,要特别注意这一点。

如果在开发单片机的时候,不确定数据有没有超过范围,可以直接在数据类型声明的头文件中查看数据值的范围。

8位单片机数据值范围

32位单片机数据值范围

/* 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

不同系统上的数据长度尽然会不一样,但是数据类型的具体范围没有规定吗?的确没有规定,C语言规范中只规定了每个数据类型的最小范围。

int — 系统给定的基本数据类型。 int类型不小于16位。

short 或者 short int — 最大的short 类型整数小于或者等于最大的int类型整数。short类型至少占16位。

long 或者 long int — 大于或等于最大的int类型整数。long型至少占32位。

long long 或者 long long int — 该类型可表示的整数大于或者等于最大的long类型整数。long long类型至少占64位。

以上是关于C语言小知识---数据类型的主要内容,如果未能解决你的问题,请参考以下文章

golang 小知识-持续更新中

C语言精华知识:表驱动法编程实践

android小知识点代码片段

c语言-数据的储存(无废话)

c语言-数据的储存(无废话)

c语言-数据的储存(无废话)