C语言宏定义的扩展定义讲解

目录
  • 1. 常量宏定义
  • 2. 定义宏函数
  • 3. 宏定义和#号结合
  • 4. 宏定义和两个#结合
  • 5. 宏定义和do…while()的结合
  • 6. #ifdef…#else…#endif
  • 7. #ifndef…#else…#endif
  • 8. #if defined() … #else … #endif

1. 常量宏定义

使用c中的#define 来定义一个常量来表示一年有多少秒

#define SECONDS_PER_YEAR (606024*365)UL

求圆的周长:

#define D® (r + r) //使用D(5) * 3.14 -----> (5 + 5) * 3.14

2. 定义宏函数

在定义宏函数时,最后一个表达式的结果就是宏函数的返回值

格式:

​ #define 宏函数名(形参表) ({语句1;语句2;语句3…})

​ 形参没有数据类型,只有参数名

请写一个“标准”的宏MIN,这个宏输入两个参数并返回较大较小值
#include <stdio.h>
#define MIN(A,B)  ({A<B?A:B;})
//宏定义分成多行书写,行尾必须加续行符
#define MAX(A,B)  ({int ret;\
                        if(A<B)\
                            ret=B;\
                        else    \
                            ret=A;\
                        ret;})
int main(int argc, char const *argv[])
{
    int min=MIN(100,200);
    printf("min value=%d\n",min);
    int max=MAX(100,200);
    printf("max value=%d\n",max);
    return 0;
}

3. 宏定义和#号结合

#可以将宏的参数转换为一个字符串

#include <stdio.h>
#define NAME "lisi"
#define NAME1(n)  n
#define NAME2(n)  #n
int main(int argc, char const *argv[])
{
	printf("%s\n",NAME);   //------>printf("%s\n","lisi");
	printf("%s\n",NAME1(lisi));   //------>printf("%s\n",lisi); //error
	printf("%s\n",NAME2(lisi));   //------>printf("%s\n","lisi"); //error
    return 0;
}

预处理之后的效果:

# 5 "test02.c"
int main(int argc, char const *argv[])
{
 printf("%s\n","lisi");
 printf("%s\n",lisi);
 printf("%s\n","lisi");
    return 0;
}

4. 宏定义和两个#结合

两个#可以实现字符串的拼接

// 将a和b代表的字符串拼接生成一个新的字符串
#define  type(a, b)     a##b

type(uint, _t)  ----> 预处理阶段展开之后的结果 : uint_t

练习:int型、short型、char型的数据比较大小

#include <stdio.h>
#if 0
int max_int(int a,int b){
    return a>b?a:b;
}
short max_int(short a,short b){
    return a>b?a:b;
}
char max_int(char a,char b){
    return a>b?a:b;
}
#endif
//使用宏定义完成函数模板
#define MAX(T) T max_##T (T a,T b){return a>b?a:b;}
//使用宏定义,定义max_int max_short max_char函数
MAX(int)
MAX(short)
MAX(char)
#define max_value(T) max_##T
int main(int argc, char const *argv[])
{
    // printf("int max value =%d \n",max_int(10000,300000));
    // printf("short max value =%d \n",max_short(100,300));
    // printf("char max value =%c \n",max_char('a','b'));
    printf("int max value =%d \n",max_value(int)(10000,300000));
    printf("short max value =%d \n",max_value(short)(100,300));
    printf("char max value =%c \n",max_value(char)('a','b'));
    return 0;
}

预处理代码:

int max_int (int a,int b){return a>b?a:b;}
short max_short (short a,short b){return a>b?a:b;}
char max_char (char a,char b){return a>b?a:b;}
int main(int argc, char const *argv[])
{
    printf("int max value =%d \n",max_int(10000,300000));
    printf("short max value =%d \n",max_short(100,300));
    printf("char max value =%c \n",max_char('a','b'));
    return 0;
}

5. 宏定义和do…while()的结合

使用场合:如果在宏定义阶段,有多条语句,最后将c语句用do…while()包裹起来

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define PRINT() printf("%s:%s:%d\n",__FILE__,__func__,__LINE__);\
              printf("%s:%s:%d\n",__FILE__,__func__,__LINE__);
#define DBUG() do{printf("%s:%s:%d\n",__FILE__,__func__,__LINE__);\
              printf("%s:%s:%d\n",__FILE__,__func__,__LINE__);}while(0)
int main(int argc, const char *argv[])
{
    int a=100,b=200;
#if 0
    /*
        调试宏:
        __FILE__:文件名
        __func__:函数名
        __LINE__:当前行号
    */
    // if(a>b){
    //     printf("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    //     printf("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    // }else{
    //     printf("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    //     printf("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    // }
    if(a>b){
        PRINT()
    }else{
        PRINT()
    }
#endif
#if 0
    //如果if或者else只有一条语句,可以省略{}
    //包括while,for循环语句都一样
    if(a>b)
        PRINT()
    else
        PRINT()
    // if和else宏替换后,变成两句,替换后语法错误,解决办法就是使用宏定义和do....while结合
#endif
    // if和else宏替换后,变成两句,替换后语法错误,解决办法就是使用宏定义和do....while结合
    if(a>b)
        DBUG();
    else
        DBUG();
    return 0;
}

6. #ifdef…#else…#endif

格式:

#define 宏定义的名字

#ifdef 宏定义的名字

​ //如果宏定义被定义了,这段代码有效

#else

​ //如果宏定义没被定义,这段代码有效

#endif

7. #ifndef…#else…#endif

格式:

#define 宏定义的名字

#ifndef 宏定义的名字

​ //如果宏定义没被定义了,这段代码有效

#else

​ //如果宏定义被定义,这段代码有效

#endif

8. #if defined() … #else … #endif

----> 底层代码使用较多

格式:
#if defined(宏定义的名字)
	// 如果宏定义被定义了,则这段代码有效
#else
	// 如果宏定义没有被定义,则这段代码有效
#endif
#if !defined(宏定义的名字)
	// 如果宏定义没有被定义,则这段代码有效
#else
	// 如果宏定义被定义了,则这段代码有效
#endif
// #if defined可以进行逻辑运算
#if defined(宏定义的名字1) || defined(宏定义的名字2)
	// 以上两个宏定义只要有一个定义了,则这段代码有效
#else
	// 以上两个宏定义都没有定义,则这段代码有效
#endif
#if defined(宏定义的名字1) && defined(宏定义的名字2)
	// 以上两个宏定义都被定义了,则这段代码有效
#else
	// 以上两个宏定义只要有一个没有定义,则这段代码有效
#endif 

到此这篇关于C语言宏定义的扩展定义讲解的文章就介绍到这了,更多相关C语言宏定义内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言#define定义宏的使用详解

    目录 1.宏是什么 2.宏的用法 3. 宏的注意事项 4. 宏和函数的区别 5.命名要求 6. 条件编译 常见条件编译指令及应用场景 1.宏是什么 #define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏(define macro). 语法: #define name( parament-list ) stuff parament-list:是一个由逗号隔开的符号表. 2.宏的用法 #define SUM(x,y) ((x)+(y)) int main

  • C语言交换奇偶位与offsetof宏的实现方法

    目录 交换奇偶位 offsetof 宏 总结 交换奇偶位 题目内容:写一个宏,可以将一个整数的二进制位的奇数位和偶数位交换. 注:二进制补码的最低位为第一位,最高位为第三十二位. 示例 1:输入:10输出:5解释:10的二进制补码为00000000000000000000000000001010,交换奇偶位后为00000000000000000000000000000101,该二进制补码为5的二进制补码,故输出为5. 思路:交换奇偶位,其实就当于将偶数位右移了一位,奇数位左移了一位.那现在的问题

  • C语言宏定义容易认不清的盲区梳理

    目录 1.概念 3.宏不是函数 4.宏定义不是说明或语句 5.宏不是类型定义 6.与之相关的宏定义 7.总结 1.概念 #define命令是C语言中的一个宏定义命令,它用来将一个标识符定义为一个字符串,该标识符被称为宏名,被定义的字符串称为替换文本. 命令有两种格式:一种是简单的宏定义,另一种是带参数的宏定义. (1)简单的宏定义: #define<宏名> <字符串> #defineVALUE((sizeof(a))/sizeof(a[0])) (2) 带参数的宏定义 #defin

  • C语言详细分析宏定义与预处理命令的应用

    目录 宏定义与预处理命令 预处理命令 - 宏定义 定义符号常量 定义傻瓜表达式 定义代码段 预定义的宏 函数 VS 宏定义 预处理命令 - 条件式编译 示例 宏定义与预处理命令 预处理阶段:处理宏定义与预处理命令: 编译期:检查代码,分析语法.语义等,最后生成.o或.obj文件: 链接期:链接所有的.o或.obj文件,生成可执行文件. 预处理命令 - 宏定义 定义符号常量 #define PI 3.1415926 #define MAX_N 10000 定义傻瓜表达式 #define MAX(a

  • C生万物C语言宏将整数二进制位的奇偶数位交换

    目录 题目分析 && 实现思路[位运算] 1.获取这个整数的奇数位和偶数位 2.使用移位运算使[奇变偶][偶变奇] 3.合并奇数位和偶数位 ⌨代码分析 1.代码展示 2.算法图解分析 总结与提炼 题目分析 && 实现思路[位运算] 首先来说一下本题的实现思路

  • 一文带你搞懂C语言预处理宏定义

    目录 预定义符号 #define #define 定义标识符 #define 定义宏 替换规则 # 和## 预定义符号 这些预定义符号都是语言内置的 __FILE__ //进行编译的源文件 __LINE__ //文件当前的行号 __DATE__ //文件被编译的日期 __TIME__ //文件被编译的时间 __STDC__ //如果编译器遵循ANSI C,其值为1,否则未定义 VS环境下未定义__STDC__ ,说明Visual Studio并未完全遵循ANSI C. #define #defi

  • C语言宏定义的扩展定义讲解

    目录 1. 常量宏定义 2. 定义宏函数 3. 宏定义和#号结合 4. 宏定义和两个#结合 5. 宏定义和do…while()的结合 6. #ifdef…#else…#endif 7. #ifndef…#else…#endif 8. #if defined() … #else … #endif 1. 常量宏定义 使用c中的#define 来定义一个常量来表示一年有多少秒 #define SECONDS_PER_YEAR (606024*365)UL 求圆的周长: #define D® (r +

  • C/C++语言宏定义使用实例详解

     C/C++语言宏定义使用实例详解 1. #ifndef 防止头文件重定义 在一个大的软件工程里面,可能会有多个文件同时包含一个头文件,当这些文件编译链接成 一个可执行文件时,就会出现大量"重定义"的错误.在头文件中实用#ifndef #define #endif能避免头文件的重定义. 方法:例如要编写头文件test.h 在头文件开头写上两行: #ifndef TEST_H #define TEST_H //一般是文件名的大写 头文件结尾写上一行: #endif 这样一个工程文件里同时

  • C语言宏定义#define的使用

    目录 无参宏定义 定义形式 带参宏定义 定义形式 #和##运算 #运算 用法: ##运算 用法: 变参宏 #ifndef 条件编译 宏定义是高级语言编译器提供的常用语法,其目的是利用某一标识符标识某个文本字符串.在编写程序时,如果程序中反复地使用某个数据或某段程序片段,就可以考虑将这个数据或程序片段定义为宏,然后每个出现该数据或程序片段的地方用宏名替代,选择宏定义来做的好处是程序简洁,可读性好,而且当需要修改这些相同的程序片段时,只要修改宏定义中的字符串即可,不需要修改多处. 宏定义命令:def

  • C++ Boost MetaStateMachine定义状态机超详细讲解

    目录 一.说明 二.示例和代码 一.说明 Boost.MetaStateMachine 用于定义状态机.状态机通过对象的状态来描述对象.它们描述了存在哪些状态以及状态之间可能存在哪些转换. Boost.MetaStateMachine 提供了三种不同的方式来定义状态机.创建状态机所需编写的代码取决于前端. 如果使用基本前端或函数前端,则可以用常规方式定义状态机:创建类,从 Boost.MetaStateMachine 提供的其他类派生它们,定义所需的成员变量,并编写所需的 C++自己编码.基本前

  • python Protobuf定义消息类型知识点讲解

    让我们从一个非常简单的例子开始.假设您想要定义"搜索请求"的消息格式.每个请求包含一个查询字符串.您对查询结果感兴趣的页数以及每页上有多少个查询结果. 可以采用如下的方式来定义消息类型的.proto文件了: syntax = "proto3"; // 声明使用 proto3 语法 message SearchRequest { string query = 1; // 每个字段都要指定数据类型 int32 page_number = 2; // 这里的数字2 是标识

  • C语言实现线索二叉树的定义与遍历示例

    本文实例讲述了C语言实现线索二叉树的定义与遍历.分享给大家供大家参考,具体如下: #include <stdio.h> #include <malloc.h> typedef char TElemType; // 二叉树的二叉线索存储表示 typedef enum{ Link, Thread }PointerTag; // Link(0):指针,Thread(1):线索 typedef struct BiThrNode { TElemType data; struct BiThrN

  • C语言在头文件中定义const变量详解

    C语言在头文件中定义const变量详解 在头文件中定义const不会有多变量的警告或错误,如果该头文件被大量包含会造成rom空间的浪费. 通过查看*.i文件的展开呢,可以发现每个.i文件都会有相应的变量展开. 查看*.map文件,能查看到该变量的多个地址分配. 在预编译的时候如果在头文件定义了const变量,每一个包含该头文件的c文件都会将其展开,而在编译的时候不会报错,因为这符合语法规则,每一个包含这个头文件的*.c文件都会编译一次这个变量,分配一个新的地址,然后在链接的时候也不会报错,因为每

  • C语言结构体数组的定义和使用详解

    目录 介绍 结构体数组定义时初始化 补充 介绍 一个结构体变量可以存放一个学生的一组信息,可是如果有 10 个学生呢?难道要定义 10 个结构体变量吗?难道上面的程序要复制和粘贴 10 次吗? 很明显不可能,这时就要使用数组.结构体中也有数组,称为结构体数组.它与前面讲的数值型数组几乎是一模一样的,只不过需要注意的是,结构体数组的每一个元素都是一个结构体类型的变量,都包含结构体中所有的成员项. 定义结构体数组的方法很简单,同定义结构体变量是一样的,只不过将变量改成数组.或者说同前面介绍的普通数组

  • Go语言学习之函数的定义与使用详解

    目录 1.函数定义 2.多值返回 3.引用传递 4.函数作为实参使用 5.匿名函数 1.函数定义 函数的定义和java一样,使用{}进行包裹,并且要明确入参类型以及返回类型. 样例代码如下: func min(num1, num2 int) int { if num1 <= num2 { return num1 } else { return num2 } } func main() { fmt.Printf("max = %d\n", min(10, 12)) } 执行结果 m

随机推荐