《电子技术应用》
您所在的位置:首页 > 可编程逻辑 > 业界动态 > 嵌入式领域,你要了解你的编译器

嵌入式领域,你要了解你的编译器

2015-09-18
关键词: 嵌入式 编译器

  我做嵌入式行业,编程也多和硬件打交道,好多人说编译器只是工具,重要的在于算法和思想。这话说的本来没错,但要有一个条件在先:那就是你真正掌握了你所用的编译器。但就我来看,真正熟悉编译器的却并不多见。当你深入了解一个编译器后,你能像用汇编一样用C,可以像汇编那样随心所欲的操作MCU!
  了解一个编译器,首先应该有汇编的基础,不要求能用汇编编写程序或做过项目,但至少看的懂!不熟悉汇编的嵌入式程序员是不合格的程序员!
  了解一个编译器,最好的方法是看它自带的帮助文件,至少要看过Compiler User's Guide ,至少遇到问题会想到到帮助中查找方法,虽然帮助大多是E文。
  工作以来一直使用keil MDK编译器,对于这个编译器的界面以及设置,可以参考博文:http://blog.csdn.net/zhzht19861011/article/details/5964827,在这里先来看一看keil MDK编译器的一些细节,看看这些细节,你知道多少。
  1. 在所有的内部和外部标识符中,大写和小写字符不同。
  2. 默认情况下,char 类型的数据项是无符号的。它们可以显式地声明为signed char 或 unsigned char。
  3.基本数据类型的大小和对齐:
  类型         位大小        按字节自然对齐
  char 8 1
  short 16 2
  int 32 4
  long 32 4
  long long 64 8
  float 32 4
  double 64 8
  long double 64 8
  所有指针 32 4
  bool (仅用于C++ ) 8 1
  _Bool (仅用于C ) 8 1
  wchar_t (仅用于C++ ) 16 2
  注:a. 通常局部变量保留在寄存器中,但当局部变量太多放到栈里的时候,它们总是字对齐的。例如局部char变量在栈里以4为边界对齐;
  b. 压缩类型的自然对齐方式为1。使用关键字__packed来压缩特定结构,将所有有效类型的对齐边界设置为1.
  4. 整数以二进制补码形式表示;浮点量按IEEE格式存储。
  5. 有符号量的右移是算术移位,即移位时要保证符号位不改变。
  6. 对于int类的值:超过31位的左移结果为零;无符号值或正的有符号值超过31位的右移结果为零。负的有符号值移位结果为-1。
  7. 整数除法的余数的符号于被除数相同,由ISO C90标准得出;
  8. 如果整型值被截断为短的有符号整型,则通过放弃适当数目的最高有效位来得到结果。如果原始数是太大的正或负数,对于新的类型 ,无法保证结果的符号将于原始数相同。所以强制类型转化的时候,对转换的结果一定要清晰。
  9. 整型数超界不引发异常;像unsigned char test;       test=1000;这类是不会报错的,赋值或计算时务必小心。
  10. 默认情况下,整型数除以零返回零。
  11. 对于两个指向相同类型和对齐属性的指针相减,计算结果如下表达式所示:
  ((int)a ? (int)b) / (int)sizeof(指向数据的类型)
  12. 在严格C中,枚举值必须被表示为整型,例如,必须在?2147483648 到+2147483647的范围内。但keil MDK自动使用对象包含enum范围的最小整型来实现(比如char类型),除非使用编译器命令??enum_is_int 来强制将enum的基础类型设为至少和整型一样宽。超出范围的枚举值默认仅产生警告:#66: enumeration value is out of "int" range
  13. 结构体:struct {
  char c;
  short  s;
  int        x;
  }          //这个结构体占8个字节
  但是,结构体:
  struct {
  char c;
  int        x;
  short  s;
  }          //这个结构体占12个字节
  这是为什么?
  对于结构体填充,据定义结构的方式,keil MDK编译器用以下方式的一种来填充结构:
  定义为static或者extern的结构用零填充;
  栈或堆上的结构,例如,用 malloc() 或者 auto定义的结构,使用先前存储在那些存储器位置的任何内容进行填充。不能使用memcmp() 来比较以这种方式定义的填充结构!
  14. 编译器不对声明为volatile 类型的数据进行优化。  我发现还有不少刚入门的嵌入式程序员从没见过这个关键字.
  15. __nop():延时一个指令周期,编译器绝不会优化它。如果硬件支持NOP指令,则该句被替换为NOP指令,如果硬件不支持NOP指令,编译器将它替换为一个等效于NOP的指令,具体指令由编译器自己决定。
  16. 还有一些编译器知识,我放在了另外一篇博文里,《有趣的keil mdk细节》。

本站内容除特别声明的原创文章之外,转载内容只为传递更多信息,并不代表本网站赞同其观点。转载的所有的文章、图片、音/视频文件等资料的版权归版权所有权人所有。本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如涉及作品内容、版权和其它问题,请及时通过电子邮件或电话通知我们,以便迅速采取适当措施,避免给双方造成不必要的经济损失。联系电话:010-82306118;邮箱:aet@chinaaet.com。