常见的嵌入式编程案列

常见的嵌入式编程案列,第1张

  【1】用#define声明一个常数,用以表示一年中有多少秒

  #define SECONDS_PER_YEAR (60*60*24*365)UL

  说明:首先,末尾#define语法末尾不能有分号;

  其次,计算式最好带括号;

  第三,这个表达式会使16位机的整型数溢出,因此需要用长整型符号L告诉编译器这个常数是长整型数,末尾用UL(无符号长整型)。

  【2】用C编写死循环

  第一种方案:while(1){}

  第二种方案:for(;;){}

  第三种方案:Loop:

  goto Loop; //这种方案是用汇编写的

  【3】访问特定内存位置:

  在某工程中,一个整型变量的绝对地址是0x67a9,请将其设置为0xaa55,并且已知编译器是一个纯粹的ANSI编译器,请编写代码

  int* ptr;

  ptr=(int*)0x67a9;

  *ptr=0xaa55;

  【4】对中断服务代码的评论

  常见的嵌入式编程案列,常见的嵌入式编程案列,第2张

  以上程序有如下几个错误:

  1、ISR不能返回一个值;

  2、ISR不能传递参数,即不能有形参;

  3、在许多处理器或编译器中,浮点数一般是不可重入的。有些处理器或编译器需要使用额外的寄存器入栈,有些处理器或编译器是不允许在ISR中做浮点运算。此外,ISR应该是短而有效率的,在ISR中做浮点运算是不明智的;

  4、printf()经常出现重入和性能上的问题,

  【5】对整数自动转换原则的理解

  常见的嵌入式编程案列,常见的嵌入式编程案列,第3张

  C语言中,整数自动转换原则是:当表达式中同时存在有符号和无符号类型时,所有的 *** 作数都自动转换成无符号类型。因此,上面程序中,第5行,a+b,a是无符号整型,b是有符号整型,二者相加,则b自动转换成无符号整型,-20变成了一个非常大的正整数,那么显然,此时a+b》6是成立的,因此,上面程序最终输出的结果是“》6”。

  【6】关键字staTIc的作用

  1、在函数体内,局部的staTI变量。作用域在函数体内,生存期却为程序的生命周期。一个被声明为静态的变量在这一函数被调用过程中维持其值不变,即本次访问该变量时访问到的是上次调用后的值。因为它被分配在静态存储区内,函数结束调用后并不释放单元,但是在其它的作用域无法访问。当再次访问这个函数时,这个局部的静态变量还存活,因此访问到的是上次调用后的值。

  2、在文件模块内(但在函数体外),一个被声明为静态的全局变量,可以被模块内所有函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。

  3、在文件模块内,一个被声明为静态的函数只可以被这个模块内的其它函数调用。即这个函数被限制在声明它的本地范围内。

  【7】与全局对象相比,使用静态数据成员有什么优势

  1、静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其它全局名字冲突的问题。

  2、使用静态数据成员可以隐藏信息,因为静态数据成员可以是private成员,而全局变量不能。

  【8】关键字volaTIle的含义

  定义为volaTIle的变量可能会被意想不到地改变,这样编译器就不会去假设这个变量的值。准确地说,优化器在用到volatile变量时必须小心地重新读取该变量的值,而不是使用保存在寄存器里的备份。使用volatile变量的地方如:

  1、并行设备的硬件寄存器(如:状态寄存器)。

  2、一个中断服务子程序中会访问到的非自动变量。

  3、多线程应用中被几个任务共享的变量。

  【9】判断处理器使用Big_endian还是Little_endian模式存储数据

  编写一个函数,若处理器使用Big_endian模式存数数据,则返回0;若是用Little_endian模式存储数据,则返回1。

  分析:首先,应该了解Little_endian和Big_endian模式有所了解,采用Little_endian模式的CPU对 *** 作数的存储方式是从低字节到高字节,而Big_endian模式对 *** 作数的存储方式是从高字节到低字节。

  例如,16位数0x1234在Little_endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:

  0x4000: 0x34

  0x4001: 0x12

  而在Big_endian模式CPU内存中的存放方式为:

  0x4000: 0x12

  0x4001: 0x34

  32位宽的数0x12345678在Little_endian模式CPU内存中的存放方式为:

  0x4000: 0x78

  0x4001: 0x56

  0x4002: 0x34

  0x4003: 0x12

  而在Big_endian模式CPU内存中存储方式为:

  0x4000: 0x12

  0x4001: 0x34

  0x4002: 0x56

  0x4003: 0x78

  该函数为:

  常见的嵌入式编程案列,常见的嵌入式编程案列,第4张

  在联合体中定义了两个成员int和char,而联合体的大小=sizeof(int)=4,因此该联合体在内存中占4个字节的大小,假设占用的内存地址为:0x1000~0x1003,那么当给a赋值1时,如果按Little_endian方式存放该数据,则:

  0x1000: 0x01

  0x1001: 0x00

  0x1002: 0x00

  0x1003: 0x00

  那么这个数值1应该存放于地址0x1000中

  而联合体有一个特性:成员都从低地址开始存放,所以当c.b=1时,那就证明数值1是存储于地址0x1000中的,那么久可以证明是Little_endian方式存储。

  如果按Big_endian方式存放a的数值1,则

  0x1000: 0x00

  0x1001: 0x00

  0x1002: 0x00

  0x1003: 0x01

  由联合体的特性可知,当以Big_endian方式存储的时候,c.b=0

  【10】判断处理器字长

  unsigned int CompareZero=~0

  cout《《hex《《CompareZero《《endl;

  【11】找错(对静态成员与非静态成员的理解)

  常见的嵌入式编程案列,常见的嵌入式编程案列,第5张

  常见的嵌入式编程案列,常见的嵌入式编程案列,第6张

  上面程序中,i为静态成员变量,func2()为静态成员函数

  第9行,test(int a):i(1),j(a) {} 根据规定,初始化列表的初始化顺序 应该与 变量声明的顺序一致,而不是按照出现在初始化列表中的顺序,从第7、8行可以看到,变量声明顺序先是i,然后再j,那么在第9行中,也应该先初始化i,再初始化j,那么此时应该i=1,j=a=2,这样看似没有错,但是,忽略了一个细节,i是静态成员变量。

  为了与非静态成员变量相区别,i是不能再类的内部被初始化的。

  可以在类的外部进行初始化,如,先把第9行改为,test(int a):j(a) {}

  然后再在第13行,添加:int test::i=1;

  第16行,定义func2函数,首先该函数为静态成员函数,它想访问静态成员变量i,以及普通变量j,但是静态成员函数只能访问静态成员变量,并不能访问非静态成员,因此无法访问j,此行应该改为:

  void test::func2() {cout《《i《《endl;}

  需要注意的是:

  1、静态数据成员必须在类外面初始化,以示与普通数据成员的区别。

  2、静态数据成员以及静态函数成员,不属于类的对象,因此没有this指针,也就无法调用类的非静态成员,它是为类的所有的对象所共享。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/dianzi/2718332.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-08-17
下一篇 2022-08-17

发表评论

登录后才能评论

评论列表(0条)

保存