栏目分类
热点资讯

C说话关键字行使技巧

发布日期:2022-01-13 13:43    点击次数:112

  1、volatile

volatile修饰外示变量是易变的,编译器中的优化器在用到这个变量时必须每次都仔细地从内存中重新读取这个变量的值,而不是行使保存在寄存器里的备份,有效的防止编译器自动优化,从而与柔件设计相相符。

休止服务与主程序共享变量:

//volatile uint8_t flag=1; uint8_t flag=1;  void test(void) {     while(flag)     {         //do something     } }  //interrupt service routine void isr_test(void) {     flag=0; } 

倘若没行使volatile定义flag,能够在优化后test陷入物化循环,由于test里行使的flag并没修改它,开启优化后,编译器能够会固定从某个内存取值。例如:

for(int i=0; i<100000; i++); //对比 for(volatile int i=0; i<100000; i++); 

前者能够被优化失踪,固然编码本意是必要实走操作延时,但编译器认为代码偶然义。

总的来说,volatile是告知编译器,不管代码如何,必须保留,而且行使时必要重新从内存读取更新,不克行使先前读取的缓存,清淡在驱动代码中行使较多。

2、const

const是恒定不变的有趣,其修饰的各栽数据相通只读奏效。

1)、 修饰变量

采用const修饰变量,即变量声明为只读,珍惜变量值以防被修改。例如

const int i = 1; 

上面这个例子外明,变量i具有只读特性,不能够被更改;若想对i重新赋值,如i = 10;属于舛讹操作。

稀奇表明,定义变量的同时进走初首化,写成int const i=1,是切确的。

2)、 修饰数组

C说话中const还能够修饰数组,举例如下:

const int array[5] = {1,2,3,4,5}; array[0] = array[0]+1; //舛讹,array是只读的,不准修改 

数组元素与变量相通,具有只读属性,不克被更改;一旦更改,编译时就会报错。

行使大数组存储固定的新闻,例如查外(外驱动法的键值外),能够行使const撙节ram。编译器并不给清淡const只读变量分配空间,而是将它们保存到符号外中,无需读写内存操作,程序实走效率也会挑高。

3)、 修饰指针

C说话中const修饰指针要稀奇仔细,共有两栽方法,一栽是用来限制指向空间的值不克修改;另一栽是限制指针不可更改。举例如下:

int i = 1; int j = 2;  const int *p1 = &i; int* const p2 = &j; 

上面定义了两个指针p1和p2,区别是const后面是指针自己照样指向的内容。

在定义1中const限制的是* p1,即其指向空间的值不可转折,若转折其指向空间的值如* p1=10,则程序会报错;但p1的值是能够转折的,对p1重新赋值如p1=&k是异国任何题目的。

在定义2中const限制的是指针p2,若转折p2的值如p2=&k,程序将会报错;但* p2,即其所指向空间的值能够转折,如* p2=20是异国题目的,程序平常实走。

4)、 修饰函数参数

const关键字修饰函数参数,对参数首限制作用,防止其在函数内部被修改。所限制的函数参数能够是清淡变量,也能够是指针变量。例如:

void fun(const int i) {     ……     i++; //对i的值进走了修改,程序报错 } 

常用的函数如strlen

size_t strlen(const char *string); 

const在库函数中行使专门普及,是一栽自吾珍惜的坦然编码思想。

3、struct与union

对于struct 组织体和union共联体在嵌入式周围是行使得专门屡次的,一些可编程芯片挑供的寄存器库都是采用组织体和共联体结相符的手段来挑供给柔件人员进走开发,同时在日常的编码过程中这两个数据类型的变通行使也能够实当代码更益的封装与简化。

如下面的浅易示例,就能够专门变通的访问Val中的bit位。

 typedef union  {      BYTE Val;      struct __packed      {         BYTE b0:1;         BYTE b1:1;         BYTE b2:1;         BYTE b3:1;         BYTE b4:1;         BYTE b5:1;         BYTE b6:1;         BYTE b7:1;     } bits; }BYTE_VAL, BYTE_BITS; 

其中:1外示按位操作。不光是位-字节能够,单字节与多字节也能够简化拼接。

#include "stdio.h"  typedef struct {     union     {         struct         {             unsigned char low;             unsigned char high;         };         unsigned short result;     }; }test_t;   int main(int argc, char *argv[]) {     test_t hello;      hello.high=0x12;     hello.low=0x34;      printf("result=X\r\n",hello.result);//输出 result=1234       return 0; } 

运走输出 result=1234 (win7编制下QT开发环境),正本必要 (high<<8)|low 运算,能够简化为共用体类型自动完善,但必须仔细平台的字节挨次,属于大端照样幼端模式。

在行使层面,倘若清晰某个数据能够存在两栽能够,而且两栽终局不会同时存在,也能够行使组织体与共用体组相符的手段,确保模块对外接口联相符。

例如移动通信模块,行使数据组织保存其基站新闻,由于制式迥异,模块能够做事在2G-GSM,也能够在4G-Cat1,为保证表层读取基站新闻接口唯一,行使共用体就专门正当,否则需定义两套接口。倘若觉得文章能够,可关注微信公多号【嵌入式编制】获取更多新闻。

4、预定义标识符

清淡编译器都声援预定义标识符,这些标识符结相符printf等打印新闻协助程序员调试程序是专门有效的,清淡编译器会自动按照用户指定完善替换和处理。

片面标识:

__FILE__    //外示编译的源文件名 __LINE__   //外示现在文件的走号 __FUNCTION__  //外示函数名 __DATE__  //外示编译日期 __TIME__   //外示编译时间 

行使范例:

printf("file:%s,line:%d,date:%s,time:%s",__FILE__,__LINE__,__DATE__,__TIME__); 

这些比较常见,主要用于日志分析、版本记录,便于调试。

5、#与##

#:是一栽运算符,用于带参宏的文本替换,将跟在后面的参数转成一个字符串常量。

##:是一栽运算符,是将两个运算对象连接在一首,也只能出现在带参宏定义的文本替换中。

#include "stdio.h"  #define TO_STR(s) #s #define COMB(str1,str2) str1##str2  int main(int argc, char *argv[]) {     int UART0= 115200;      printf("UART0=%d\n", COMB(UART, 0));//字符串相符并为变量UART0     printf("%s\n", TO_STR(3.14));//将数字变成字符串      return 0; } 
6、void 与 void*

void外示的是无类型,不克声明变量或常量,但是能够把指针定义为void类型,如void* ptr。void* 指针能够指向肆意类型的数据,在C说话指针操作中,肆意类型的数据地址都可转为void* 指针。由于指针内心上都是unsigned int。

常用的内存块操作库函数:

void * memcpy( void *dest, const void *src, size_t len ); void * memset( void *buffer, int c, size_t num); 

数据指针为void* 类型,对传入肆意类型数据的指针都能够操作。另外其中memcpy第二个参数,const现在也如前文所述,拷贝时对传入的原数据内容不准修改。

稀奇表明,指针是不克行使sizeof求内容大幼的,在ARM编制固定为int 4字节。对于函数无输入参数的,也尽量添上void,如

void fun(void); 
7、weak

清淡简化定义

#define _WEAK __attribute__((weak))   

函数名称前线添上__WEAK属性修饰符称为“弱函数”,相通C++的虚函数。链接时优先链接为非weak定义的函数,倘若找不到则再链接带weak函数。

_WEAK void fun(void)   {       //do this }    //不在联相符个.c,两同名函数不克在联相符个文件 void fun(void)   {       //do that }   

这栽自动选择的机制,在代码移植和多模块协调做事的场景下行使较多。例如前期移植代码,必要调用某个接口fun,但现在该接口不存在或者未移植完善行使,能够行使weak关键字定义为空函数先保证编译平常。后续移植完善实现了fun,即柔件中有2个fun函数异国任何舛讹,编译器自动会识别行使后者。自然也强横的#if 0屏蔽对fun的调用,但要确保后续记得铺开。

8、总结

存在即相符理,C说话内里的关键字,每个都有其稀奇的意义,只是清淡行使较少,譬如作文,行使常用的汉字能够;但旁征博引,行使稀奇的修饰辞藻更能显出程度。后续对section 进走详细表明,它和动态添载(OTA)、接口自启动有关。

本文转载自微信公多号「嵌入式编制」,能够经历以下二维码关注。转载本文请有关嵌入式编制公多号。

【编辑选举】

鸿蒙官方战略相符作共建——HarmonyOS技术社区 C说话在STM32中的内存分配 盘点那些益用的C说话编程柔件工具 第一个C说话编译器是怎样编写的? 浅析五栽C说话内存分配的手段及区别 【C说话】动画讲解C说话

友情链接:

Powered by 不付费黄的美女视频软件-草草免费视频新地址手机官网-可以看裸 @2013-2021 RSS地图 HTML地图

Copyright 365站群 © 2013-2021 365建站器 版权所有