看到这个题目好多人肯定会迷惑,数据类型有什么可说的,这不是编程的基础吗?凡是会写代码的肯定都熟悉数据类型,不就是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语言小知识---数据类型相关推荐

  1. C语言基础知识-数据类型

    C语言基础知识-数据类型 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.常量与变量 1>.关键字 C的关键字共有32个.1>.数据类型关键字(12个)char,sh ...

  2. 纸上得来终觉浅(c语言小知识总结)

    纸上得来终觉浅(c语言小知识总结) 1.数组的初始定义 对于一个初始定义的数组,内部的值是随机的,若用{}(哪怕其中没有元素)也会让数组内元素初始化,默认为0. 若是用循环语句进行赋值,在一个长度为2 ...

  3. eem二级c语言题库哪种比较好,c语言小知识,供初学者参考

    1 用预处理指令 define 声明一个常数 用以表明 1 年中有多少秒 忽略闰年问题 define SECONDS PER YEAR 60 60 24 365 UL 2 写一个 标准 宏 MIN 这 ...

  4. C语言小知识:typedef\函数模板\

    (1)typedef用法: typedef为C语言的关键字,作用是为一种数据类型定义一个新名字.这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等).在编程中使用t ...

  5. C语言小知识---特殊的字符串

      字符串在程序中很常见,和整数.小数.字符其他数据类型一样,是代码中必不可少的一部分.可是字符串却又和其他类型不完全一样,还有自己的个性.   下面直接通过一段代码来看. 定义了一个字符1.一个字符 ...

  6. C语言小知识---递归函数的使用

      C语言允许函数自身调用自身,这种调用就被称为递归.好多人刚开始学习递归的时候,往往被一层层嵌套调用搞糊涂了,搞不清楚到底是怎么调用的?现在就通过一个小例子来演示一下,递归调用时,函数是如何运行的. ...

  7. C语言小知识---为什么要使用指针

      刚开始学习C语言的时候,感觉最难理解的就是指针,什么指针变量,变量指针,指向指针的变量,指向变量的指针?一堆概念,搞得人云里雾里的,今天不讨论这些概念的问题,从最底层来分析C语言中为什么要使用指针 ...

  8. C语言小知识---奇葩的小数

      看到这个标题,好多人可能会想,小数有什么奇葩的,这不和整数一样,加减乘除计算起来也没啥区别呀?奇葩在哪里?   下面通过一个简单的例子来看一看,定义一个小数一个整数,然后打印出来. 核心代码其实只 ...

  9. C语言小知识---printf()函数转换符的意义

      printf()函数大家已经很熟悉了,它的转换符在打印数据的时候也会经常使用,比如%c,%d,%f等.那么为什么打印的时候一定需要转换符呢?系统难道不能自动识别吗?转换符存在的意义又是什么?    ...

最新文章

  1. Ktor 1.0发布:JetBrains推出的Kotlin Web框架
  2. Jquery 日期差函数 修改 对火狐进行兼容
  3. 服务器主机装普通系统后性能下降,服务器主机性能分析
  4. python第一课教案_Python第一课
  5. [生产库实战] 如何使用触发器对生产库上亿级大表进行实时同步
  6. JVM 字节码 对照表
  7. ALM TFS/VSTS工具 的Java集成
  8. 数据结构上机实践第七周项目2 - 自建算法库——链队(链式队列)
  9. 机器学习and深度学习学习资料
  10. 前端直接读取文本文件内容
  11. 塞班系统微信连接不上服务器,充满情怀的塞班系统:手机QQ、微信将无法登陆使用...
  12. [面试] 步步为营:吉大学士的PG宝洁面经
  13. 最详细移动硬盘安装linux过程,装在移动硬盘上的linux系统不能在另一台电脑启动的解决办法
  14. 物业收费管理系统 java_基 于java的小区物业收费管理系统.doc
  15. StampedLock(印戳锁)详解
  16. STM32学习之路——麒麟座V3.2开发板蜂鸣器发声问题
  17. 云平台运维的一些心得
  18. 系统对接方案_钉钉报销单对接财务系统解决方案
  19. @Embedded 和 @Embeddable
  20. openstack 本地导入镜像.

热门文章

  1. 2nd day in SG
  2. SAP BPC最佳实践-BPC系统备份及恢复
  3. 企业内网安全十大防护策略
  4. Fedora10使用若干问题
  5. hdu-5867 Water problem(水题)
  6. 发布水晶报表时需要在服务器进行如下操作
  7. vagrant配置虚拟机网卡
  8. Springboot中使用websocket发送信息给指定用户和群发
  9. 浅谈如何进行测试用例管理
  10. Selenium API-WebDriver 属性