_I,_O,_IO,条件编译#ifndf _HEAD_H中的下划线_是什么,有什么用

2023-10-26

1.其实质是一个宏名。由此我们可以防止发生重复定义或声明。
2.编程风格,使标识符含义更清晰易懂

假设你的头文件名为head.h,根据习惯,我们声明一个宏HEAD_H,对应这个头文件,在头文件中开始的地方和结尾的地方加上 对HEAD_H的声明和判断,头文件Head.h如下:

#ifndef HEAD_H
#define HEAD_H

……(头文件内容)

#endif

这样,头文件可以避免被多次包含。头文件中定义的变量不存在重复声明或定义。

对于 条件编译_HEADH_H前的下划线

  1. 是可以写成 LED.H只不过你接下来要写一句#defined LED.H 因为#ifndef 后面的字符串 不管是 LED.H还是__LED_H和头文件的名字没有半毛钱关系。只不过是为了读程序的时候方便而已。其实那个字符串只要合法的就行了。
  2. 用法 :
    #ifndef 字符串 #define 上述字符串 #endif 一般放在头文件里面,作用就是以防你在.c文件里面不小心重复包含头文件的时候不会报错。 例如,现在你有 main.c LED.H 两个文件。 如果你在main函数里面两次包含头文件LED.H。即 #include “LED.h” #include “LED.h” int main(void) { return 0; } 那么你的程序肯定会报错。因为你的头文件重复添加了。
    但是如果你在LED.H里面动一点手脚就把问题解决了,在LED.H添加如下代码 #ifndef abcdefg #define abcdefg #include “stm32f10x.h” void led_init(void); …//其他函数声明 #endif 就可以把问题解决。 分析如下:#ifndef 的是if no define----”如果没有定义“的意思。带#的是预编译命令,在编译之前执行。 如果没有定义abcdefg 那么就#define abcdefg 定义了abcdefg 当你多次包含LED.H这个头文件的时候。第一次肯定是没有定义的,所以肯定会执行 #define abcdefg 但是第二次,第三次,…以后再包含的时候,由于第一次已经定义过了abcdefg字符串,所以第二次的#ifndef abcdefg 不成立,所以往下的语句就不会执行。那么就不会重复包含头文件了。也不会把头文件里面声明过的函数再继续重复声明了。也就不会报错了。所以记住一点:#ifndef 在头文件里的用法是通过判断这个字符串是否被定义过,从而决定是否跳过某些语句来达到,条件编译,防止报错的效果的。 当然条件编译的用处很灵活看你怎么用。

小结一下:#if 表达式 程序段1 #endif 第二种: #ifndef 表达式 程序段2 #endif 第三种 #ifdefine 表达式 程序段3 #endif 以上是三种基本的条件编译,当然可以嵌套。

那_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说明,因为每次对它的读写都可能由不同意义;

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:输入输出口,同上

为什么加下划线?

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

转载于[(https://blog.csdn.net/chuckfql/article/details/8684207?utm_medium=distribute.pc_relevant.none-task-blog-2defaultBlogCommendFromMachineLearnPai2default-1.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2defaultBlogCommendFromMachineLearnPai2default-1.no_search_link)]

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

_I,_O,_IO,条件编译#ifndf _HEAD_H中的下划线_是什么,有什么用 的相关文章

  • unity在同屏幕显示多Camera并在脚本中修改Viewport Rece

    参考 https www it610 com article 1305219586412548096 htm 参考 https www zhihu com question 41879088 sort created 修改Camera的Vi
  • 开放平台认证方案

    背景 本次的直接起因是第三方那边接入系统后端引起的 第三方方觉得认证要过期比较麻烦 而且要用账号密码去调登录接口去刷token 设计不合理 客观来说 凭本人使用过其它开放平台来说确实有些不一样 常见的一些开放平台 有带web的 一般web能
  • 感知机及算法实现

    1 感知机二类分类的线性分类模型 输入为实例的特征向量 输出为实例的类别 取 1和 1二值 感知机对应于输入空间中将实例划分为正负两类的分离超平面 属于判别模型 感知机学习旨在求出将训练数据进行线性划分的分离超平面 为此导入基于误分类的损失
  • error: use of deleted function

    本文案例仅供参考 出错的代码如下 TEST Test test1 TestImpl impl TestImpl para1 para2 ASSERT EQ jkj impl func 22 33 44 实际应该这样 TEST Test te
  • PyCharm下载包出错

    PyCharm安装成功之后添加所需的包 File gt Settings gt Project 此处是你的Python工作环境 gt Project Interpreter 红色剪头所指 添加需要的包 点开时候出现错误信息 Error lo

随机推荐

  • phpstorm运行php出现502 Bad Gateway

    个人博客开通啦 功能正在逐步完善中 大家可以访问http www codeliu com 记一次心碎的经历 我用的phpstorm10 0 1 XAMPP 今天写完一个php文件后 运行出现502 Bad Gateway的错误 明明上一刻还
  • c语言中的常见数据类型

    一 常见的数据类型包括基本类型 枚举类型 空类型和派生类型 基本类型又包括整型类型 浮点类型 整型类型 基本类型 int 短整型 short int 长整型 long int 双长整型 long long int 字符型 char 布尔型
  • 判断一个字符是否是十六进制

    判断一个字符是否是十六进制 十六进制 hexadecimal 是计算机中数据的一种表示方法 意思是逢十六进一 十六进制数以16为基数 采用的数码是0 1 2 3 4 5 6 7 8 9 A B C D E F 其中A F分别表示十进制数字1
  • JAVA中的异常处理

    一 什么是异常 异常是指在程序执行过程中出现的错误或异常情况 它可能是由于错误的输入 无效的操作 资源不可用等原因引起的 当程序遇到异常时 它会中断当前的执行路径 并转到能够处理该异常的代码块 在 Java 中 异常是以对象的形式表示的 它
  • PID串行多闭环控制与并行多闭环控制的优缺点分析和应用比较

    导言 在自动控制领域 PID控制器是一种经典的控制策略 被广泛应用于各种工业和非工业过程 随着控制系统的复杂性增加 PID串行多闭环控制和PID并行多闭环控制成为解决复杂控制问题的重要方法 本文将从优点和缺点的角度对这两种控制策略进行对比
  • Android基础之Fragment

    目录 前言 一 Fragment简介 二 Fragment的基础使用 1 创建Fragment 2 在Activity中加入Fragment 1 在Activity的layout xml布局文件中静态添加 2 在Activity的 java
  • 数学建模--粒子群算法(PSO)的Python实现

    目录 1 开篇提示 2 算法流程简介 3 算法核心代码 4 算法效果展示 1 开篇提示 开篇提示 这篇文章是一篇学习文章 思路和参考来自 https blog csdn net weixin 42051846 article details
  • 宝峰对讲机16频率表_宝峰888S对讲机的16个信道频率是多少?

    1 宝峰888S对讲机 16个工作频率范围为 400 470MHZ 16个信道 频率范围内 任意频道任意频率 内 2 一般对讲机没容有固定频点 出厂都是空频机器 每个信道的频率都可以写成机器频率范围内的任意频点也可以空白什么都不写 3 根据
  • 矩阵求逆四种方法

    注 用A B表示某矩阵 E表示单位矩阵 用A 表示A逆 用 A 表示A的行列式 A E 表示拼接矩阵 一 公式法 先求A行列式结果 再求A伴随矩阵 最后再求A逆矩阵 A 0 则 A A A 注 图片中detA就是 A 二 初等变换法 A E
  • 【沧海拾昧】Proteus8仿真stm32:ADC转换程序

    C0102 沧海茫茫千钟粟 且拾吾昧一微尘 沧海拾昧集 CuPhoenix 阅前敬告 沧海拾昧集仅做个人学习笔记之用 所述内容不专业不严谨不成体系 如有问题必是本集记录有谬 切勿深究 目录 一 原理图绘制 二 多位七段数码管 三 ADC引脚
  • 一维动态规划总结

    题目列表 给一个N 输入 求某种情况的最大值或者最小值情况 279 Perfect Squares 思路 最差情况下 总体是定义一个dp N 1 或者初始化前面dp 0 或者dp 1 279 Perfect Squares 解析 Given
  • sql:command not found

    写一个脚本zl sh 用来删除数据库mydatabase中某个表mytable的某行数据 bin bash HOSTNAME 127 0 0 1 PORT 2918 USERNAME root PASSWORD root TABLENAME
  • 使用mockjs创建假数据

    npm install mockjs 创建mock文件夹 在mock文件夹下创建1 js 1 js import Mock from mockjs 引入mockjs export default Mock mock postdata1 po
  • 剑网三服务器缺少必要启动文件,win7系统玩剑网三游戏经常掉线的解决方法

    很多小伙伴都遇到过win7系统玩剑网三游戏经常掉线的困惑吧 一些朋友看过网上零散的win7系统玩剑网三游戏经常掉线的处理方法 并没有完完全全明白win7系统玩剑网三游戏经常掉线是如何解决的 今天小编准备了简单的解决办法 只需要按照1 掉线基
  • 循环神经网络RNN以及几种经典模型

    RNN简介 现实世界中 很多元素都是相互连接的 比如室外的温度是随着气候的变化而周期性的变化的 我们的语言也需要通过上下文的关系来确认所表达的含义 但是机器要做到这一步就相当得难了 因此 就有了现在的循环神经网络 他的本质是 拥有记忆的能力
  • el-menu-item内容过多,不能滚动

    问题描述 这里放了六张图片 只能看到最下面的部分 上面的部分被挤出了屏幕外面 这里的弹出框是element ui组件自动生成的 即这个div 我此时有关这部分的代码如下 解决思路 一开始是想抓住这个生成的div 修改这个div的样式试图让它
  • python 2.x安装

    1 查看当前python版本 python version 2 安装最新2 x版本 brew install python 2 安装完成后 注意一下提示 pip and setuptools have been installed To u
  • 阻碍区块链应用落地的五大难题和解决方案

    2018年初区块链掀起了一阵新热潮 多家互联网公司纷纷宣布推出区块链项目 新兴的区块链项目方和媒体百家争鸣 一时之间区块链行业风光无限 区块链概念的火爆 使得越来越多的人开始学习它 理解它 甚至 拥抱 它 只是沉浸在 狂欢 里的众人怎么也没
  • show,attend and tell(image caption论文复现总结)

    论文中的核心思想 GitHub上的Image Caption项目https github com sgrvinod a PyTorch Tutorial to Image Captioning 研究的问题 Image Caption 为图片
  • _I,_O,_IO,条件编译#ifndf _HEAD_H中的下划线_是什么,有什么用

    1 其实质是一个宏名 由此我们可以防止发生重复定义或声明 2 编程风格 使标识符含义更清晰易懂 假设你的头文件名为head h 根据习惯 我们声明一个宏HEAD H 对应这个头文件 在头文件中开始的地方和结尾的地方加上 对HEAD H的声明