__I、 __O 、__IO是什么意思? 
这是ST库里面的宏定义,定义如下:

#define     __I       volatile const        /*!< defines 'read only' permissions      */
#define     __O     volatile                  /*!< defines 'write only' permissions     */
#define     __IO    volatile                  /*!< defines 'read / write' permissions   */

显然,这三个宏定义都是用来替换成 volatile 和 const 的,所以我们先要了解 这两个关键字的作用:

volatile 
简单的说,就是不让编译器进行优化,即每次读取或者修改值的时候,都必须重新从内存或者寄存器中读取或者修改。

一般说来,volatile用在如下的几个地方:
1、中断服务程序中修改的供其它程序检测的变量需要加volatile;
2、多任务环境下各任务间共享的标志应该加volatile;
3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;

我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。搞嵌入式的家伙们经常同硬件、中断、RTOS等等打交道,所有这些都要求用到 volatile变量。不懂得volatile的内容将会带来灾难。假设被面试者正确地回答了这是问题(嗯,怀疑是否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。 
1)一个参数既可以是const还可以是volatile吗?解释为什么。 
2); 一个指针可以是volatile 吗?解释为什么。 
3); 下面的函数有什么错误:

int square(volatile int *ptr)
{   return *ptr * *ptr;
}  
1)是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
2); 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。
3) 这段代码有点变态。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:
int square(volatile int *ptr)
{   int a,b;   a = *ptr;  b = *ptr;  return a * b;
}  

由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:

long square(volatile int *ptr)
{   int a;   a = *ptr;  return a * a;
}   

const 
只读变量,即变量保存在只读静态存储区。编译时,如何尝试修改只读变量,则编译器提示出错,就能防止误修改。 
const与define 
两者都可以用来定义常量,但是const定义时,定义了常量的类型,所以更精确一些(其实const定义的是只读变量,而不是常量)。#define只是简单的文本替换,除了可以定义常量外,还可以用来定义一些简单的函数,有点类似内置函数。const和define定义的常量可以放在头文件里面。(小注:可以多次声明,但只能定义一次)

const与指针
int me;
const int * p1=&me;           //p1可变,*p1不可变             const 修饰的是 *p1,即*p1不可变
int * const p2=&me;           //p2不可变,*p2可变             const 修饰的是 p2,即p2不可变
const int *const p3=&me;   //p3不可变,*p3也不可变       前一个const 修饰的是 *p3,后一个const 修饰的是p3,两者都不可变

前面介绍了 volatile 和 const 的用法,不知道大家了解了没?了解了后,下面的讲解就更加容易了: 
__I :输入口。既然是输入,那么寄存器的值就随时会外部修改,那就不能进行优化,每次都要重新从寄存器中读取。也不能写,即只读,不然就不是输入而是输出了。 
__O :输出口,也不能进行优化,不然你连续两次输出相同值,编译器认为没改变,就忽略了后面那一次输出,假如外部在两次输出中间修改了值,那就影响输出 
__IO:输入输出口,同上

为什么加下划线?

原因是:避免命名冲突 
一般宏定义都是大写,但因为这里的字母比较少,所以再添加下划线来区分。这样一般都可以避免命名冲突问题,因为很少人这样命名,这样命名的人肯定知道这些是有什么用的。 
经常写大工程时,都会发现老是命名冲突,要不是全局变量冲突,要不就是宏定义冲突,所以我们要尽量避免这些问题,不然出问题了都不知道问题在哪里。

__I、 __O 、__IO是什么意思?相关推荐

  1. STM32第一课(Keil, Type, macro)

    keil中建立工程 在目标文件夹下,新建四个文件夹, core, hallib, obj, user. 在keil中,project->new uvision project,定位到建立的use ...

  2. C语言 volatile的作用与使用场景

    今天完成公司的任务,突然想起来在调试过程中遇到了一个问题是这样的:"我在主函数里面写了一个while(x)的循环,想在中断里面去改变这个变量x,以达到主函数里面退出while循环的目的.但是 ...

  3. __I、__O、__IO什么意思和处于keil里面什么位置

    1.位于keil 的core_cm3.h里面 2. #define __I volatile const /*!< defines 'read only' permissions */ #def ...

  4. 【C语言】关键字volatile之有关__IO、__O、__I的故事

    文章目录 前言 1.有关volatile的故事 2.顺带一提的const 3.__IO.__O.__I的缘起 前言   在阅读意法官方给的STM32固件库的工程中的时候偶然看见了_IO修饰的变量然后发 ...

  5. __I、 __O 、__IO是什么意思?怎么用?

    原文: http://www.chuxue123.com/forum.php?mod=viewthread&tid=122&extra=page%3D1 __I. __O .__IO是 ...

  6. 关于STM32库中 __IO 修饰符(volatile修饰符,反复无常的意思)

    STM32例子代码中会有像这样的代码 static __IO uint32_t TimingDelay;  这里边的__IO修饰符不好理解,单从字面可以看出是为IO相关,查其标准库可以得知这个__IO ...

  7. STM32 keil中__IO得意思

    __IO解释 STM32得库函数中(HAL和LL库都有),存在一个__IO得宏定义 #define __I volatile const /*!< defines 'read only' per ...

  8. c语言Int16_t 什么意思,__IO uint16_t 是什么意思,在定义参数时为什么不直接写成 uint16...

    满意答案 lsdiddeuf28 2013.09.15 采纳率:42%    等级:12 已帮助:8813人 STM32里的类型定义,见如下说明: /* Exported types -------- ...

  9. ARM中 __IO的作用解析

    __IO在头文件中预定义 #define __IO volatile volatile 影响编译器编译的结果, 指出:volatile 变量是随时可能发生变化的,与volatile变量有关的运算,不要 ...

最新文章

  1. python3 的range
  2. metasploit快速入门(二)收集信息
  3. Spring boot的Spring MVC扩展功能
  4. 博客积分规则 博客等级
  5. Django中扩展Paginator实现分页
  6. DotNetAnywhere:可供选择的 .NET 运行时
  7. 2018-12-25 上机作业
  8. 被面试官问懵:TCP 四次挥手收到乱序的 FIN 包会如何处理?
  9. 怒江java培训班_怒江万词霸屏是什么意思
  10. 【Oracle】ORA-04031错误解决
  11. 民族融合 —— 魏晋南北朝
  12. python opcua_理解python中的免费OPC/UA代码
  13. AcWing 143. 最大异或对 —— 神奇的二进制
  14. iOS 面向切面编程与typhoon框架
  15. 超详细电烙铁如何使用?
  16. 音视频处理基础知识扫盲:数字视频YUV像素表示法以及视频帧和编解码概念介绍
  17. 牛客网刷题笔记-SQL 25 获取员工其当前的薪水比其manager当前薪水还高的相关信息
  18. 数字从后往前每三位加个逗号
  19. 去哪儿网支付系统架构演进
  20. 一个实验了解多层内网渗透

热门文章

  1. 十个经典的Android开源项目
  2. c语言编译kbhit出现问题,kbhit用C语言
  3. 本题要求从输入的N个整数中查找给定的X。如果找到,输出X的位置(从0开始数);如果没有找到,输出“Not Found”
  4. springboot 启动banner 打印 佛祖保佑
  5. RPG Maker MV 计时器的用法
  6. 码农视角: iPhone XR升级到iOS 14.2之后引发的惨案
  7. PostgreSQL 中的系统字段:tableoid、xmin、xmax、cmin、cmax、ctid
  8. k8s - Service ExternalName
  9. 物理机安装esxi系统
  10. 2017多校第4场 HDU 6078 Wavel Sequence DP