先上源代码:

  文件为portmacro.h,来源于Dynasty项目中的底层代码(NVIC中断控制部分)

 1 #define portNVIC_INT_CTRL_REG        ( * ( ( volatile uint32_t * ) 0xe000ed04UL ) )
 2 #define portNVIC_PENDSVSET_BIT        ( 1UL << 28UL )
 3
 4
 5 void vPortYield( void )
 6 {
 7     /* Set a PendSV to request a context switch. */
 8     portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
 9
10     /* Barriers are normally not required but do ensure the code is completely
11     within the specified behaviour for the architecture. */
12     __DSB();
13     __ISB();
14 }

  这一句让我懵逼了.

1 portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;

宏定义还可以赋值!!?以往的认知都是宏定义为常量,常量不可以被赋值,所以宏一般都是出现在操作符的右侧!!

#define portNVIC_INT_CTRL_REG        ( * ( ( volatile uint32_t * ) 0xe000ed04UL ) )

虽然这句话我可以看懂,portNVIC_INT_CTRL_REG 代表 0xe000ed04UL 地址中的值。为了验证,测试程序如下
 1 #define MACRO_A     ( * ( ( volatile uint32_t * ) 0x20000300 ) )
 2 #define MACRO_B     200
 3 #define MACRO_C      (a)
 4
 5 int a = 10;
 6
 7 void MacroTest()
 8 {
 9     int nVal = 50;
10
11     PWAPP_TRACE(("MACRO_C: %d", MACRO_C));
12
13     MACRO_C =  20;
14     PWAPP_TRACE(("MACRO_C: %d", MACRO_C));
15     PWAPP_TRACE(("MACRO_A: %d", MACRO_A));
16     PWAPP_TRACE(("address: %d",( * ( ( volatile uint32_t * ) 0x20000300 )) ));
17     MACRO_A = MACRO_B;
18
19     PWAPP_TRACE(("MACRO_A: %d", MACRO_A));
20     PWAPP_TRACE(("MACRO_B: %d", MACRO_B));
21
22     MACRO_A = nVal;
23     PWAPP_TRACE(("MACRO_A: %d", MACRO_A));
24
25     return;
26 }

  测试的结果为:

  [PWAPP][MacroTest], line[1230]>>>MACRO_C: 20
  [PWAPP][MacroTest], line[1233]>>>MACRO_C: 20
  [PWAPP][MacroTest], line[1235]>>>MACRO_A: 50
  [PWAPP][MacroTest], line[1236]>>>address: 0
  [PWAPP][MacroTest], line[1240]>>>MACRO_A: 200
  [PWAPP][MacroTest], line[1241]>>>MACRO_B: 200
  [PWAPP][MacroTest], line[1244]>>>MACRO_A: 50

  结果显示还真是可以给宏赋值。

  贴上宏的定义:

  计算机科学里的宏(Macro),是一种批量批处理的称谓。一般说来,宏是一种规则或模式,或称语法替换 ,用于说明某一特定输入(通常是字符串)如何根据预定义的规则转换成对应的输出(通常也是字符串)。这种替换在预编译时进行,称作宏展开。

  发现定义中有意思的点在于这个“语法替换”,。

  当宏定义值本身为常量时,这个宏就替换为一个常量,

    如:“#define MACRO_B 200”,MACRO_B就不可以被重新赋值。

  当宏定义本身代表了一个变量时,这个宏就替换了这个变量,也就同时拥有了该变量可以被赋值的特点,

    如

    “#define MACRO_C (a)

    int a = 10;”

  此时MACRO_C代替了整形变量a,同时MACRO_C也可以被赋值。

  而#define MACRO_A ( * ( ( volatile uint32_t * ) 0x20000300 ) )实质上和#define MACRO_C (a)是一样的。 * ( ( volatile uint32_t * ) 0x20000300 和a代表的相同的意思。

  所以,MARCO是否能够在之后的代码中被赋值,取决于宏在被定义时代表的是常量还是变量。

  其实还有一个很重要的应用问题,虽然MACRO可以被重新赋值,但是在实际代码中使用MACRO来代替变量是否合适呢?也就说应用场景有哪些? 

  常有的用法一般都是用宏来代替常量,因为宏的定义可以清楚的表示该常量的意义。

  而 #define MACRO_A ( * ( ( volatile uint32_t * ) 0x20000300 ) ) 这种用法的个人猜测意义在于可以直接访问硬件地址或驱动的寄存器,在底层的代码中应用的机会会比较多。同时也可以让开发者清楚的知道该地址的意义。如之前的

1 #define portNVIC_INT_CTRL_REG        ( * ( ( volatile uint32_t * ) 0xe000ed04UL ) )

  就是NVIC驱动控制寄存器的代表。

  目前关于这种宏赋值的用法能想到的基本就只有这些,可能还有其他的应用场景,希望大家能够补充~

  最后祝大家身体健康~

转载于:https://www.cnblogs.com/simon-code/p/5629743.html

让人懵逼的宏定义赋值相关推荐

  1. 51单片机c语言宏定义是什么意思,51单片机的C语言宏定义应用.doc

    1.预编译处理是单片机C语言程序设计中经常用到的一种方法.通过一些预处理命令可以为C语言本身提供许多功能和符号的扩充,增强C语言程序的灵活性和方便性. 常用的预处理命令有:宏定义.文件包含.条件编译等 ...

  2. c++宏定义常量为什么使用移位_干货 | C语言系列3——常量,运算符,常用数学函数.........

    本期总结 1.符号常量和const常量: 2.运算符: 3.输入与输出: 4.常用数学函数. 往期回顾 干货 | C语言系列1--编程软件与做题平台 干货 | C语言系列2--程序结构与变量 符号常量 ...

  3. VC预处理指令与宏定义的妙用

    VC中预处理指令与宏定义的妙用 刚接触到MFC编程的人往往会被MFC 向导生成的各种宏定义和预处理指令所吓倒,但是预处理和宏定义又是C语言的一个强大工具.使用它们可以进行简单的源代码控制,版本控制,预 ...

  4. #define宏定义是什么?怎么写?一文搞懂。

    前言 第一次接触宏定义的时候,是在学校的C++课程大作业中.当时有幸看到了大佬写的源码,里面有很多的宏定义.当时并不了解宏定义的妙用,只感觉它像是定义了一个变量一样,不好理解还有些多此一举. 这之后在 ...

  5. C语言中宏定义使用方法详解

    C语言中的宏替换详解 首先看一个问题: #include <stdio.h> #define    PRINT_CLINE()    printf("%d", ____ ...

  6. 【转自猫大】宏定义的黑魔法 - 宏菜鸟起飞手册

    宏定义在C系开发中可以说占有举足轻重的作用.底层框架自不必说,为了编译优化和方便,以及跨平台能力,宏被大量使用,可以说底层开发离开define将寸步难行.而在更高层级进行开发时,我们会将更多的重心放在 ...

  7. 枚举(enum)、宏定义(#define)、结构体(struct)的拾遗

    1.宏定义 1.1.不带参数的宏定义 #define 标识符 字符串           例如:#define PI 3.1415926 说明: (1)宏名一般习惯用大写字母表示,但并非规定,也可以用 ...

  8. C++ const关键字的总结(全局/局部变量、修饰指针和引用、成员函数和数据成员、修饰类对象、const与宏定义的区别、Static与Const的区别)

    const关键字 const关键字 1.什么是const 2.使用原理 2.1.const全局/局部变量 2.2.cosnt修饰指针和引用 2.3.const修饰函数参数 2.4.const修饰函数返 ...

  9. 如何用C语言改变宏定义的大小,C语言中宏定义使用的小细节

    C语言中宏定义使用的小细节 #pragma#pragma 预处理指令详解 在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作.#p ...

最新文章

  1. C语言编写的PHP框架--yaf入门编程
  2. canvas绘制时钟
  3. android 网络调试 源代码,一个步骤教你调试Android系统源代码
  4. java poi3.15 ppt,Apache POI PPT - 演示( Presentation)
  5. python PIL/Pillow图像扩展、复制、粘贴处理
  6. 笔记本老出现计算机,电脑老是自动重启,教您如何有效解决这个问题
  7. html5 自制播放器
  8. 第一节 Java语言发展史
  9. Ubuntu 17.04 壁纸设计大赛 已经开幕
  10. django连接mysql_Django 连接数据库
  11. ROS的优势与不足(除了ROS 机器人自主定位导航还能怎么做?)
  12. inout口简单说明
  13. matlab的小波分析,matlab小波分析步骤是什么
  14. Region和Available Zone的区别
  15. 何同学采访苹果CEO库克上热搜,网友表示自愧不如
  16. GCC编译器使用指北
  17. 改写[转载]关闭危险端口的批处理文件FOR WIN7
  18. 【卡尔曼滤波介绍与原理解析】
  19. 嵌入式专业英文词汇汇总
  20. 使用 WPF+ ASP.NET MVC 开发 在线客服系统 (一)

热门文章

  1. 2020工作第一天,免费请大家喝星巴克咖啡了,速来!
  2. 无线系列 - MIMO波束赋形技术研究
  3. 阿里云有奖调查!赠10个阿里巴巴logo胸针
  4. ubuntu下git搭建服务器(gitosis)
  5. 增加firefox的搜索选项
  6. 课后自主练习(排序)1027. 极坐标排序 easy《编程思维与实践》个人学习笔记
  7. 千锋深圳校区相亲会 双蛋之夕不再孤单
  8. 推荐一款类似微软visio的免费软件
  9. ROS:rosbag play系列指令(详解)
  10. ssh端口转发(隧道技术)