[应用相关]

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

[复制链接]
958|1
手机看帖
扫描二维码
随时随地手机跟帖
heimaojingzhang|  楼主 | 2018-9-15 21:27 | 显示全部楼层 |阅读模式
原文网址:https://blog.csdn.net/zhzht19861011/article/details/6361591

了解一个编译器,首先应该有汇编的基础,不要求能用汇编编写程序或做过项目,但至少看的懂!不熟悉汇编的嵌入式程序员是不合格的程序员!

      了解一个编译器,最好的方法是看它自带的帮助文件,至少要看过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.基本数据类型的大小和对齐:


类型        位大小       按字节自然对齐
char81
short162
int324
long324
long long648
float324
double648
long double648
所有指针324
bool (仅用于C++ )81
_Bool (仅用于C )81
wchar_t (仅用于C++ )162

注: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细节》


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


mmuuss586| | 2018-12-23 17:35 | 显示全部楼层
感谢分享;

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

74

主题

3832

帖子

4

粉丝