嵌入式C语言技术积累

技术积累

1、时间复杂度和空间复杂度

时间复杂度:

      指执行当前算法所消耗的时间

空间复杂度:

      指当前当前算法需要占用多少的内存

2、Struct

1)字节对齐

自然对齐(即默认对齐方式):是指按结构体的成员中size最大的成员对齐

指定对齐

      使用伪指令 #pragma pack (n) ,编译器将按照n个字节对齐

      使用伪指令#pragma pack () , 取消自定义字节对齐方式

(注意:如果#pragma pack (n)中指定的n大于结构体中最大成员的size,则不起作用,结构体仍然按照size最大的成员进行对齐。)

2)与Class 对比

    • Struct 中成员变量默认为public ,而Class 中成员变量默认为private
    • Struct 可以在定义时直接以{ }的形式对齐成员变量进行赋值

3、Extern “C”

   1)被Extern “C” 修饰的变量和函数是按照C语言方式编译和连接的。

      2)如果在模块A中函数声明了foo为extern “C”类型,而模块B中包含的是extern int foo(int x,int y),则模块B找不到模块A中的函数。

      3)在C中引用C++中的函数和变量时,C++的头文件需添加extern “C”,但是在C语言中不能直接引用声明了extern C的该头文件。

4、C高效编程技巧

      1)以空间换时间

           使用宏函数代替函数:

==========================

#define bwMCDR2_ADDRESS 4
#define bsMCDR2_ADDRESS 17
#define bmMCDR2_ADDRESS BIT_MASK
(MCDR2_ADDRESS)
#define BIT_MASK(_bf)(((1U<<(bw##_bf))-1)<<
(bs##_bf)
#define SET_BITS(_dst,_bf,_val)\
((_dst)=((_dst)&~(BIT_MASK(_bf)))I
(((_val)<<(bs##_bf))&(BIT_MASK(_bf))))
SET_BITS(MCDR2,MCDR2_ADDRESS,RegisterNumb
er);

==========================

函数和宏函数的区别在于:宏函数占用了大量的空间,而函数占用时间。函数调用是要使用系统的栈来保存数据,同时CPU也要在函数调用时保存和恢复当前的现场,进行压栈和弹栈操作。

2)数学方法解决问题

      ============================

I=(100*(1+100))/2

============================

3)使用位操作

      使用位操作,减少除法和取模的运算

      ============================

I=257>>3;

============================

4)嵌入汇编

5、预处理

 1)#error

      Q:预处理器标识#error的目的是什么?

      A:保证程序是按照所设想的方式执行

6、变量a的8种定义用法

  • 一个整型数:int a
  • 一个指向整型数的指针: int *a
  • 一个指向指针的指针,它指向的指针是指向一个整型数: int **a
  • 一个有10个整型数的数组: int a[10];
  • 一个有10个指针的数组,该指针是指向一个整型数的。: int *a[10];
  • 一个指向有10个整型数数组的指针:int (*a)[10];
  • 一个指向函数的指针,该函数有一个整型参数并返回一个整型数: int (*a)(int);
  • 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数:int (*a[10])(int);

 

7、函数指针 VS 指针函数

1)指针函数

本质是一个函数,该函数的返回值是一个指针,声明格式如下:

      类型标识符* 函数名(参数表)

指针函数的声明如下:

        int *fun (int x,int y);

注意:

  在调用指针函数时,需要用同一个类型的指针来接收其函数的返回值。

2)函数指针

           函数指针,其本质是一个指针变量,该指针指向这个函数,其声明格式:

      类型说明符 *函数名)(参数)

函数指针的声明如下:

int (*fun) (int x,int y);

8、关键字const

      const 意味着“只读”,const是定义常变量的关键字,使用const关键字的作用:

  1. 为阅读代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉用户这个参数的应用目的
  2. 通过给优化器一些附加的信息
  3. 是编译器保护那些不希望被改变的参数,防止被无意的代码修改

9、关键字volatile

      Volatile修饰的变量意味着可能会被意想不到的改变。精确地说,优化器在用到这个变量时,必须每次小心地重新读取这个变量的值,而不是使用保存在寄存器里面的备份。Volatile 实例

    • 并行设备的硬件寄存器
    • 一个中断服务子程序中会访问到的非自动变量
    • 多线程应用中被几个任务共享的变量。

注意点:

  1. 一个参数既可以是const的还可以是volatile? 为什么?

可以的,它是volatile因为它可能被意想不到的改变,它是const因为程序不应该试图修改它

  1. 一个指针可以是volatile?为什么?

可以的,例如:当一个中断服务程序指向一个buffer的指针时

  1. 下面的函数有什么错误?该如何修改

int square(volatile int *ptr)
{
return *ptr * *ptr;
}

             ======================

           答:因为*ptr 可能被意想不到的修改,所以两次*ptr的值可能不一样,导致结果并非为想要的平方值。正确代码应该如下:

long square(volatile int *ptr)
{
int a;

a = *ptr;
return a * a;

}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值