zoukankan      html  css  js  c++  java
  • keil mdk编译器学习笔记(3)——转载+整理

    目前keil mdk已经更新到5.29,很多新的功能,可以尝试,体验。公司项目可以使用老的编译器,自己玩玩可以谭毅新的版本的keil。

    我做嵌入式行业,编程也多和硬件打交道,好多人说编译器只是工具,重要的在于算法和思想。这话说的本来没错,但要有一个条件在先:那就是你真正掌握了你所用的编译器。但就我来看,真正熟悉编译器的却并不多见。当你深入了解一个编译器后,你能像用汇编一样用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.基本数据类型的大小和对齐:float需要特别注意,经过测试,占用4个字节。

    注:a. 通常局部变量保留在寄存器中,但当局部变量太多放到栈里的时候,它们总是字对齐的。例如局部char变量在栈里以4为边界对齐;

             b. 压缩类型的自然对齐方式为1。使用关键字__packed来压缩特定结构,将所有有效类型的对齐边界设置为1.,这个我在另一篇文章里面已经调试过。

            4. 整数以二进制补码形式表示;浮点量按IEEE格式存储。浮点数比较特别注意,同时,我还使用了ti的定点浮点库,这个可以加速代码运行,尤其是没有硬件fpu的单片机来说,可以尝试。

            5. 有符号量的右移是算术移位,即移位时要保证符号位不改变。

            6. 对于int类的值:超过31位的左移结果为零;无符号值或正的有符号值超过31位的右移结果为零。负的有符号值移位结果为-1。

            7. 整数除法的余数的符号于被除数相同,由ISO C90标准得出;

            8. 如果整型值被截断为短的有符号整型,则通过放弃适当数目的最高有效位来得到结果。如果原始数是太大的正或负数,对于新的类型 ,无法保证结果的符号将于原始数相同。所以强制类型转化的时候,对转换的结果一定要清晰。

            9. 整型数超界不引发异常;像unsigned char test;       test=1000;这类是不会报错的,赋值或计算时务必小心。

            10. 默认情况下,整型数除以零返回零。不过通常情况下,软件里面需要做 保护,被除数为0,则另外计算

            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细节》。

    后记:关于Keil MDK的应该掌握的知识,在《编写优质嵌入式C程序》一文的第三章中,做了进一步总结,可以直接查看该文。

    原文链接:https://blog.csdn.net/zhzht19861011/article/details/6361591

  • 相关阅读:
    小程序开发系列(五)悬浮搜索框
    LINQ的连接扩展(左连、右连、全连等)
    小程序开发系列(四)九宫格另一种实现
    python 生成随机图片验证码
    django定时任务小插件
    线程池模块thernd
    python logging 模块记录日志
    django Q条件
    jquery 事件绑定
    jQuery示例
  • 原文地址:https://www.cnblogs.com/CodeWorkerLiMing/p/12120434.html
Copyright © 2011-2022 走看看