条件编译 #和##运算符

目录

  • 1. #运算符
  • 2. ##运算符
  • 3. 条件编译
  • 4. 题目分享
  • 总结


正文开始

前言: 本章为C语言语法完结撒花, 下文将进行C语言中#和##操作符以及条件编译的讲解, 来进一步让我们了解C语言.
作者主页: 酷酷学!!!

1. #运算符

#运算符将宏的⼀个参数转换为字符串字⾯量。它仅允许出现在带参数的宏的替换列表中。
#运算符所执⾏的操作可以理解为”字符串化“。

当我们有⼀个变量 int a = 10; 的时候,我们想打印出: the value of a is 10 .
就可以写:

#define PRINT(n) printf("the value of "#n " is %d", n);

当我们按照下⾯的⽅式调⽤的时候:

PRINT(a);//当我们把a替换到宏的体内时,就出现了#a,⽽#a就是转换为"a",时⼀个字符串

代码就会被预处理为:

printf("the value of ""a" " is %d", a);

运⾏代码就能在屏幕上打印:

the value of a is 10

2. ##运算符

##可以把位于它两边的符号合成⼀个符号,它允许宏定义从分离的⽂本⽚段创建标识符。 ## 被称为记号粘合
这样的连接必须产⽣⼀个合法的标识符。否则其结果就是未定义的。

这⾥我们想想,写⼀个函数求2个数的较⼤值的时候,不同的数据类型就得写不同的函数。

int int_max(int x, int y)
{
 return x>y?x:y;
}
float float_max(float x, float y)
{
 return x>y?x:y;
}

但是这样写起来太繁琐了,现在我们这样写代码试试:

//宏定义 
#define GENERIC_MAX(type) \
type type##_max(type x, type y)\
{ \
 return (x>y?x:y); \
}

使⽤宏,定义不同函数

GENERIC_MAX(int) //替换到宏体内后int##_max ⽣成了新的符号 int_max做函数名 
GENERIC_MAX(float) //替换到宏体内后float##_max ⽣成了新的符号 float_max做函数名 
int main()
{
 //调⽤函数 
 int m = int_max(2, 3);
 printf("%d\n", m);
 float fm = float_max(3.5f, 4.5f);
 printf("%f\n", fm);
 return 0;
}

输出:

3
4.500000

3. 条件编译

在编译⼀个程序的时候我们如果要将⼀条语句(⼀组语句)编译或者放弃是很⽅便的。因为我们有条件编译指令。

⽐如说:

调试性的代码,删除可惜,保留⼜碍事,所以我们可以选择性的编译。
#include <stdio.h>
#define __DEBUG__

int main()
{
    int i = 0;
    int arr[10] = { 0 };
    for (i = 0; i < 10; i++)
    {
        arr[i] = i;
#ifdef __DEBUG__
        printf("%d\n", arr[i]);//为了观察数组是否赋值成功。  
#endif //__DEBUG__
    }
    return 0;
}

常⻅的条件编译指令:

1.
#if 常量表达式
//...
#endif
//常量表达式由预处理器求值。 
如:
#define __DEBUG__ 1
#if __DEBUG__
//..
#endif

2.多个分⽀的条件编译
#if 常量表达式
//...
#elif 常量表达式
//...
#else
//...
#endif

3.判断是否被定义
#if defined(symbol)
#ifdef symbol

#if !defined(symbol)
#ifndef symbol

4.嵌套指令
#if defined(OS_UNIX)
	#ifdef OPTION1
		unix_version_option1();
	#endif
	
	#ifdef OPTION2
		unix_version_option2();
	#endif
	
#elif defined(OS_MSDOS)
	#ifdef OPTION2
		msdos_version_option2();
	#endif
	
#endif

4. 题目分享

  1. 写一个宏,计算结构体中某变量相对于首地址的偏移,并给出说明
    考察:offsetof宏的实现
#include<stdio.h>
#define offset(structType, MemberName) ((size_t)&((structType*)0)->MemberName)

struct stu
{
	char name[10];
	int age;
	char sex[10];
};

int main()
{
	size_t ret = 0;
	ret = offset(struct stu, age);
	printf("%d\n", ret);
	return 0;
}


运行结果:

在这里插入图片描述

代码分析:

//Struct是结构体类型名,MenberName是成员名.
//1、先将0转换为一个结构体类型的指针,
// 相当于某个结构体的首地址是0。
// 此时,每一个成员的偏移量就成了相对0的偏移量,
// 这样就不需要减去首地址了。
//
//2、对该指针用->访问其成员,并取出地址,
// 由于结构体起始地址为0,此时成员偏移量直接相当于对0的偏移量,
// 所以得到的值直接就是对首地址的偏移量。
//
//3、取出该成员的地址,强转成size_t并打印,就求出了这个偏移量。
  1. 写一个宏,可以将一个整数的二进制位的奇数位和偶数位交换。
#define SWAP_BITS(num) (((num & 0xAAAAAAAA) >> 1) | ((num & 0x55555555) << 1))

代码分析:

//交换奇偶位,需要先分别拿出奇偶位。
//既然是宏,分别拿出用循环不是很现实,
//那就用& 这些位的方式来做。奇数位拿出,
//那就是要& 上010101010101……,偶数位拿出,
//就是要& 上101010101010……,对应十六进制分别是555……和aaa……,
//一般我们默认是32位整数,4位对应一位16进制就是8个5,8个a。
//通过 & 0x55555555的方式拿出奇数位和 & 0xaaaaaaa的方式拿出偶数位。
//奇数位左移一位就到了偶数位上,偶数位右移一位就到了奇数位上,
//最后两个数字或起来,就完成了交换

总结

以上是本文的全部内容, 如果觉得有帮助还望点赞收藏, 如有错误恳请指正

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/568177.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

牛客社区所有的表和SQL语句

文章目录 1 帖子表 discuss_post1.1 字段描述1.2 相关功能描述1.2.1 分页查询帖子1.2.2 查询帖子总数量1.2.3 插入一条帖子记录1.2.4 根据帖子ID查询某条帖子1.2.5 更新帖子评论数量1.2.6 更新帖子类型1.2.6 更新帖子状态1.2.7 更新帖子分数 2 用户表 user2.1 字段描述2.2 相关…

cesium primitive 移动 缩放 旋转 矩阵

旋转参考&#xff1a;cesium 指定点旋转rectangle Primitive方式 矩阵篇-CSDN博客 平移参考&#xff1a;cesium 调整3dtiles的位置 世界坐标下 相对坐标下 平移矩阵-CSDN博客 一、primitive方式添加polygon let polygonInstance new Cesium.GeometryInstance({geometry: Ce…

陆金所控股一季报到底是利好还是利空?

3月底&#xff0c;陆金所控股&#xff08;LU.N;06623.HK&#xff09;因其特别分红方案受到市场高度关注。但在4月23日发布的2024年一季度财报中&#xff0c;陆金所控股营收同比下降30.9%&#xff0c;净亏损8.3亿元。 两者对比&#xff0c;外界不由得对公司的经营状况产生疑惑。…

ROS 话题订阅模型之自定义消息类型 C++实现

ROS 话题订阅模型之自定义消息类型 1.自定义消息类型好处 ROS提供了许多标准的消息类型&#xff0c;如 std_msgs/String、sensor_msgs/Image 等&#xff0c;涵盖了很多常见的数据类型和传感器数据。但是&#xff0c;在实际的开发中&#xff0c;我们经常会遇到需要传输的数据类…

【Image captioning】论文阅读九—Self-Distillation for Few-Shot Image Captioning_2022

摘要 大规模图像字幕数据集的开发成本高昂,而大量未配对的图像和文本语料库可能有助于减少手动注释的工作。在本文中,我们研究了只需要少量带注释的图像标题对的少样本图像标题问题。我们提出了一种基于集成的自蒸馏方法,允许使用不成对的图像和字幕来训练图像字幕模型。该…

springcloud alibaba 整合seata的TCC

一、seata服务端搭建同上篇。 Seata的AT模式客户端两阶段提交流程源码分析 二、seata客户端的结构 1.示例DEMO工程 下单&#xff0c;扣余额&#xff0c; 减库存。 2. MAVEN配置。 父工程&#xff1a;由于spring-cloud-starter-alibaba-seata依赖的seata-spring-boot-starter…

C语言(static和extern)

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸各位能阅读我的文章&#xff0c;诚请评论指点&#xff0c;关注收藏&#xff0c;欢迎欢迎~~ &#x1f4a5;个人主页&#xff1a;小羊在奋斗 &#x1f4a5;所属专栏&#xff1a;C语言 本系列文章为个人学习笔记&#x…

Python写个二维码

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、进入官网下载二、下载一下三.输入代码 前言 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、进入官网下载 官网 pip insta…

FR-E840-0120-4-60 三菱变频器5.5KW型

FR-E840-0120-4-60 三菱变频器替换FR-E740-5.5K FR-E840用户手册,FR-E840-0120-4-60价格,FR-E840-5.5K价格,FR-E840-0120-4-60外部连接图,FR-E740-5.5K替换产品。 FR-E740-5.5K-CHT逐渐开始停产&#xff0c;现在用新型号FR-E840-0120-4-60替换。 FR-E840-0120-4-60参数说明&…

2024年前端技术发展趋势

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

anaconda安装python 3.8环境

打开anaconda命令行窗口 在命令行窗口中&#xff0c;输入命令&#xff1a;conda create -n py38 python3.8 执行命令后&#xff0c;显示conda版本、安装路径和安装的包 然后提醒是否安装&#xff0c;输入y 等待安装完成。然后进入python3.8&#xff0c;执行命令&#xff1a;con…

全网最全的平行坐标图(parallel coordinates plot)的绘制攻略

早上起来拥抱太阳&#xff0c;写小论文&#xff0c;看到人家的图怎么那么好看&#xff01;&#xff01;&#xff1f;&#xff1f; 这不得赶紧抄下来&#xff0c;我也发一个顶刊&#xff1f;于是开始思考如何解决绘制这个问题&#xff0c;目前现有的大部分解决方案都是直接调库…

【计算机毕业设计】理发店管理系统产品功能说明——后附源码

&#x1f389;**欢迎来到我的技术世界&#xff01;**&#x1f389; &#x1f4d8; 博主小档案&#xff1a; 一名来自世界500强的资深程序媛&#xff0c;毕业于国内知名985高校。 &#x1f527; 技术专长&#xff1a; 在深度学习任务中展现出卓越的能力&#xff0c;包括但不限于…

Python Selenium无法打开Chrome浏览器处理自定义浏览器路径

问题 在使用Python Selenium控制Chrome浏览器操作的过程中&#xff0c;由于安装的Chrome浏览器的版本找不到对应版本的驱动chromedriver.exe文件&#xff0c;下载了小几个版本号的驱动软件。发现运行下面的代码是无法正常使用的&#xff1a; from selenium import webdriver …

HWOD:合并整型数组

一、知识点 合并整型数组目前有两种方法 合并数组并不一定需要真正的合并 1、下意识的方法 对两个整型数组分别排序&#xff0c;然后合并 2、不排序的方法 遍历两个数组&#xff0c;找出最小值&#xff0c;输出最小值。将两个数组中与最小值相等的位置置为超大值 重复以…

二叉树oj题(2)

1.二叉树的最近公共祖先 解题思路&#xff1a;方法一&#xff1a; 1.先判断p或者q 是不是 root当中的一个 2.左子树当中递归査找p或者q 3.右子树当中递归查找p或者q 如何查找: root 的 left 和 right 都不为空 ->root root的 left 为空 right 不为空->right这一侧找…

终于有人说明白了session、cookie和token的区别

一、首先介绍一下名词&#xff1a;Session、cookie、token&#xff0c;如下&#xff1a; 1.Session会话&#xff1a;客户端A访问服务器&#xff0c;服务器存储A的数据value&#xff0c;把key返回给客户端A&#xff0c;客户端A下次带着key&#xff08;session ID&#xff09;来…

ROS轻松入门(一)—— 基本概念:node节点、topic通信、service通信

node节点 ROS 中的每个节点都应该负责单一的、模块化的目的&#xff0c;例如控制车轮马达或发布来自激光测距仪的传感器数据。每个节点都可以通过主题、服务、操作或参数从其他节点发送和接收数据。 一个完整的机器人系统由许多协同工作的节点组成。在 ROS 2 中&#xff0c;单…

【java配置】jpcap的下载与idea配置

解决报错&#xff1a;Cannot resolve symbol ‘jpcap’ 1. jpcap的下载 官网下载链接 百度网盘下载 双击WinpPca安装&#xff0c;jacap1和jpcap2任选其中之一 2. idea配置 &#xff08;1&#xff09;查看当前使用jdk目录 File -> Project Settings -> SDKs &#…

STM32H750时钟频率和功耗以及RTC功能测试

STM32H750时钟频率和功耗和RTC功能测试 &#x1f4cc;相关篇《STM32H750片外QSPI启动配置简要》 ✨在使用STM32CubeMX修改STM32H750时钟树参数时&#xff0c;如果使用软件自动求解&#xff0c;这是一个非常耗时的操作&#xff0c;有时候还不一定成功&#xff0c;还是推荐使用手…