#define 宏的高级用法(转)

一,宏的定义与撤销

#普通宏定义
#define PI 3.14    //编译阶段替换掉宏
#define T1 3+4     //容易产生歧义
#define T2 (3+4)   //添加括号后,语义清楚

float r = 1.0;
float area = PI * r * r;
int a = 2* T1    #宏替换后变成   int a = 2*3+4     不符合本意
ing a = 2* T2    #红替换后变成   int a = 2*(3+4)   符合本意   

#undef PI
float area = PI * r * r;     #error: ‘PI’ was not declared in this scope

//引号中的宏定义不会被替换
printf("%s:%f\n", "PI", PI);    //输出 PI:3.14

//宏定义的名字必须是合法标识符
#define 0x abcd    //error 不能以数字开始

//宏定义中双引号和单引号必须成对出现
#define TEST11 "Z    //error
#define TEST2 ‘Z     //error

二、带有参数的宏定义

//max和min的宏定义带参数
#define MAX(a,b) (a>b ? a:b)
#define MIN(a,b) (a<b ? a:b)

//使用带参数的宏定义
int sum= MAX(1,2) + MIN(1,2);    //替换后语句为:int sum = (1>2 ? 1:2) + (1<2 ? 1:2)

//参数个数必须宏定义时形参的个数相同
MAX(1,2,3);    //会报错

#undef MAX    //撤销MAX的宏定义
MAX(1,2);    //error: ‘MAX’ was not declared in this scope

三、跨行的宏定义 使用反引号\连接

#定义一个交换数值的多行宏,使用反斜杠连接不同行
#define SWAP(a,b) do {     int t = 0;    t = a;     a = b;     b = t; } while(0)

四,三个特殊符号:#,##,#@

#define CONNECT(a,b) a##b
#define TOCHAR(a) #@a
#define TOSTRING(a) #a

//a##b表示连接
int n = CONNECT(123, 456);                //结果  n = 123456
char *str = CONNECT("abcd", "efg");       //结果  str = "abcdefg"

//@#a 表示用单引号包括参数a,返回的是一个字符
char * ch1 = TOCHAR(1);        //结果  ch = ‘1‘
char * ch2 = TOCHAR(123);      //报错,单引号只用在单个字符里

//#a 表示用双引号包括参数a,返回一个字符串
char * str1 = TOSTRING(123);    // str = "123"

五、常见的宏定义

  • 防止头文件被重复包含
#ifndef BODYDEF_H
#define BODYDEF_H 

//头文件内容 

#endif
  • 得到指定地址上的一个字节值或字值
#include "stdio.h"
//B表示字节byte
#define MEM_B( x )  ( *( (byte *) (x) ) )
//B表示字word,可以理解为int
#define MEM_W( x )  ( *( (word *) (x) ) )

int main()
{
    int bTest = 0x123456;

    byte m = MEM_B((&bTest));    /*m=0x56*/
    int n = MEM_W((&bTest));     /*n=0x3456*/

    return 0;
}
  • 得到一个field在结构体(struct)中的偏移量
#define OFFSETOF( type, field ) ( (size_t) &(( type *) 0)-> field )
  • 得到一个结构体中field所占用的字节数
#define FSIZ( type, field ) sizeof( ((type *) 0)->field )
  • 得到一个变量的地址(word宽度)
#define B_PTR( var ) ( (byte *) (void *) &(var) )
#define W_PTR( var ) ( (word *) (void *) &(var) )
  • 将一个字母转换为大写
#define UPCASE( c ) ( ((c) >= ‘a‘ && (c) <= ‘z‘) ? ((c) - 0x20) : (c) )
  • 判断字符是不是10进值的数字
#define DECCHK( c ) ((c) >= ‘0‘ && (c) <= ‘9‘)
  • 判断字符是不是16进值的数字
#define HEXCHK( c ) ( ((c) >= ‘0‘ && (c) <= ‘9‘) ||((c) >= ‘A‘ && (c) <= ‘F‘) ||((c) >= ‘a‘ && (c) <= ‘f‘) )
  • 防止溢出的一个方法
#define INC_SAT( val ) (val = ((val)+1 > (val)) ? (val)+1 : (val))
  • 返回数组元素的个数
#define ARR_SIZE( a ) ( sizeof( (a) ) / sizeof( (a[0]) ) )

原文地址:https://www.cnblogs.com/linxw-blog/p/12696881.html

时间: 2024-11-10 07:31:55

#define 宏的高级用法(转)的相关文章

Visual Studio 宏的高级用法

我已经介绍了如何编写一个最简单的宏,本文将进一步介绍如何用宏来实现对代码编辑窗口控制.在本文结束的时候,你应该能自己实现如下两个功能,第一个用于对方法体进行 phase0 标记:第二个可以将当前窗口中的代码进行归类,将所有方法.属性.变量通过region进行分块. 动画演示:phase0 动画演示:设置 region 为什么使用宏 在计算机行业内,宏的出现由来已久,因为它能替代人们执行一些重复发生的简单但烦琐的事情,所以广受人们欢迎.在 Visual Studio 中也提供了进行宏编程的方法,从

C++宏的高级用法

#ifndef __GNUC__     #error 编译器为g++,windows下,好像没有把##生成的新字符串当成一个宏处理 #endif #define conn(x,y)    x#y // x必须是一个字符串,使用时,conn("2",3),而不能是conn(2,3),3可以是任何类型的字符串 // ## 有两种用法,一种是字符串连接,另一种是把连接生成的字符串当成一个新的宏 // 新宏必须存在 // 用##连接中参数中包含已定义的宏时,宏不会展开 #define STR

#define的高级用法

=========================================================== define中的三个特殊符号:#,##,#@ =========================================================== #define Conn(x,y) x##y #define ToChar(x) #@x #define ToString(x) #x (1)x##y表示什么?表示x连接y,举例说: int n = Conn(12

#define命令的一些高级用法

=========================================================== define中的三个特殊符号:#,##,#@ =========================================================== #define Conn(x,y) x##y #define ToChar(x) #@x #define ToString(x) #x (1)x##y表示什么?表示x连接y,举例说: int n = Conn(12

iOS自动布局高级用法及纯手码约束写法

本文主要介绍几个我遇到的总结的高级用法(当然我相信肯定有不少比这还高级的). 简单的storyboard中上下左右约束,固定宽高啥的用法在这里就不做赘述了. autolayout自动布局是iOS6以后出现的,但是在开始的一段时间里大家并不怎么会用,都是一上来先勾掉.之后随着5s,iPhone6的出现屏幕多种多样.用多层if来判断尺寸已经完全hold不住了才开始学习自动布局. 在这之前有个叫自动伸缩的autoresizing属性,这个主要用于一个控件和自己父控件之间的关系.只有autolayout

C语言宏的高级应用

原文:C语言宏的高级应用 关于#和##在C语言的宏中,#的功能是将其后面的宏参数进行字符串化操作(Stringfication),简单说就是在对它所引用的宏变量通过替换后在其左右各加上一个双引号.比如下面代码中的宏: #define WARN_IF(EXP) do{ if (EXP) fprintf(stderr, "Warning: " #EXP "); } while(0) 那么实际使用中会出现下面所示的替换过程: WARN_IF (divider == 0);被替换为

C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com

原文:C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 本文由 arthinking 发表于315 天前 ⁄ itzhai.com原创文章 ⁄ C语言 ⁄ 评论数 3 ⁄ 被围观 1,775 views+ 指针数组: 在一个数组中,如果它的元素全部都是指针类

jquery on高级用法

on()的高级用法 针对自己处理机制中,不仅有on方法,还有根据on演变出来的live方法(1.7后去掉了),delegate方法等等.这些方法的底层实现部分 还是on方法,这是利用了on的另一个事件机制委托的机制衍变而来的 委托机制 .on( events ,[ selector ] ,[ data ], handler(eventObject) ) 在on的第二参数中提供了一个selector选择器,简单的来描述下 参考下面3层结构 <div class="left">

typedef与define宏定义用于声明新的类型之间的区别

摘自<c专家编程> typedef可以看成一种彻底的封装类型,在typedef声明类型之后不能再往里面增加其他的内容. 例子: #define peach int unsigned peach i; //没问题 typedef int banana; unsigned banana i; //错误,不能增加unsigned #define宏定义只是用于简单的替换 #define int_ptr int * int_ptr chalk, cheese; int * chalk, cheese;