C语言程序设计:预处理命令

预处理命令

基础知识

预处理命令简介

在这里插入图片描述

C语言的预处理命令是指编译之前预处理器执行的指令,用于在源代码中进行一些预处理操作。

常见预处理命令

(1) #define

定义一个宏,用于替换源代码中的标识符为指定的文本

#define MAX_NUM 100
int arr[MAX_NUM];// 替换后就是:int arr[100];

(2) #include

包含一个头文件,头文件中的内容插入源代码中。

#include <stdio.h>  // 使用尖括号,从系统目录中查找头文件
#include "myHeader.h"  // 使用双引号,从当前目录查找头文件

(3)#ifdef#ifndef

用于条件编译,根据指定的宏是否已经定义来决定是否编译某段代码。

#ifndef DEBUG
printf("Debug mode is off\n");
#endif

(4)#if / #elif / #else / #endif

用于条件编译,根据指定的表达式来决定是否编译某段代码。

#define NUM 100
#if NUM > 50
printf("NUM is greater than 50\n");
#elif NUM < 50
printf("NUM is less than 50\n");
#else
printf("NUM is equal to 50\n");
#endif

(5)undef

主要用于取消宏定义,使得后面可以再次定义相同名宏定义

#define PI 3.1415
#undef PI//取消宏

(6)#pragma

用于向编译器发出特殊指令

#pragma warning(disable: 4996)//(禁用指定警告)

宏定义

宏的三种用法

(1)定义符号常量

#define PI 3.1415926
#define MAX_N 100000

(2)定义傻瓜表达式

#define MAX(a, b) ((a) > (b) ? (a) : (b))//求较大值
#define S(a, b) ((a) * (b))//求乘积

(3)定义代码段

宏只允许实现在一行,需要多行的话可以用\拼接。

#define P(a) {\printf("%d\n", a);\
}

预定义宏

_ _ DATE _ _:日期:Mmm dd yyyy
_ _TIME _ _ : 时间:hh:mm:ss
_ _LINE _ _:行号:
_ _FILE _ _:文件名
_ _func _ _ : 函数名(非标准)
_ _ FUNC _ _ :函数名(非标准)
_ _ PRETTY_FUNCTION _ _更详细的函数信息

变参宏

(1)相关介绍

  • 一种宏定义方式,允许宏接受可变数量的参数。它的作用类似于函数中的可变参数函数(例如printf函数),可以在宏中处理不定数量的参数。

(2)两种实现方式

  • 变参宏的实现原理主要涉及两个预处理器运算符:__VA_ARGS__##
  • __VA_ARGS__是一个特殊标识符,表示宏的可变参数部分(即省略号 …)。它在宏展开时会被替换为实际的参数列表。
  • ##运算符将前面的标记与后面的标记连接在一起,可以用于在可变参数宏中正确地处理参数之间的逗号

// ##方式

#define LOG(fmt, arg...) {\printf("[FILE: %s FUNC: %s LINE: %d]\t", __FILE__, __func__, __LINE__ );\printf(fmt, ##arg);\printf("\n");\
}int main(){int num = 10, a = 123;LOG("num = %d, a = %d\n", num, a);LOG("Hello word\n");
}

//特殊宏 _ _ VA_ARGS _ _

 /*实现变参宏*/
#include<stdio.h>
#define LOG(...) {\printf("[FILE: %s FUNC: %s LINE: %d]\t", __FILE__, __func__, __LINE__);\printf(__VA_ARGS__);\
}int main(){int num = 10, a = 123;LOG("num = %d, a = %d\n", num, a);LOG("Hello word\n");
}

条件式编译

(1)简单介绍

  • #ifdef DEBUG:是否定义了DEBUG这个宏;
  • ifndef DEBUG:是否没定义DEBUG宏;
  • if MAX_N == 5:宏MAX_N是否等于5
  • #else:其他情况
  • #endif: 结束当前条件判断

(2)实现一个LOG宏

#include<stdio.h>
#ifdef DEBUG
#define LOG(fmt, arg...) {\printf("[FILE: %s FUNC: %s LINE: %d] ", __FILE__, __func__, __LINE__ );\printf(fmt, ##arg);\printf("\n");\
}
#else
#define LOG(fmt, arg...)
#endifint main(){int a = 12;LOG("%d",a);return 0;
}

扩展知识

(1)__typedef()关键字

  • __typeof()关键字是C语言的一个扩展,它的作用是获取表达式或变量的类型信息不执行实际的操作。
  • __typeof()的具体实现是通过编译器在编译阶段进行静态分析来确定表达式或变量的类型,并将其替换为相应的类型。

//实现swap操作

#define swap(a, b) {\__typedef((a)) __c = (a);\(a) = (b);\(b) = __c;\
}

(2)__attribute__属性

  • __attribute__((constructor))是GCC和一些兼容的编译器提供的一个特殊属性,它用于指定在程序启动时自动执行的函数。这个特性可以用来实现在程序运行前执行一些初始化操作的需求。
  • 当函数被标记为__attribute__((constructor))时,编译器会将该函数添加到一个特殊的构造函数表中。在程序启动时,链接器会在运行时初始化阶段执行这个构造函数表中的函数。具体来说,这些带有constructor属性的函数将在main()函数之前被自动调用
#include<stdio.h>
char *usr;
char *phone;
__attribute__((constructor))
void init() {usr = "mofei";phone = "132312123";return ;
}
int main() {printf("usr : %s \nphone : %s\n", usr, phone);return 0;
}

(3)#的作用

  • #是一种预处理器运算符,称为字符串化运算符。
  • 它的作用是将宏参数转换为字符串常量。
  • 当使用#运算符在宏定义中对参数进行字符串化时,它会在编译时将参数表示为一个字符串。
#include<stdio.h>
#define str(a) {\printf("%s : %d\n", #a, a);\
}
int main() {int A = 123;str(A);return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

神经网络应用

⚠申明&#xff1a; 未经许可&#xff0c;禁止以任何形式转载&#xff0c;若要引用&#xff0c;请标注链接地址。 全文共计3077字&#xff0c;阅读大概需要3分钟 &#x1f308;更多学习内容&#xff0c; 欢迎&#x1f44f;关注&#x1f440;【文末】我的个人微信公众号&#xf…

NXP i.MX8系列平台开发讲解 - 3.10 Linux PCIe资源分配与访问(二)

目录 1. PCIe BFD 2. PCIe 配置空间 2.1 PCIe 配置空间访问 PCIe I/O访问方法 PCIe MMIO访问方法 3. PCIe BAR相关 4. PCIe Capbility 5. PCIe 操作 本文将重点讲解PCIe的资源访问相关内容&#xff0c;对于PCIe资源访问是从Host 端老看可以对PCIe进行配置与访问的资源主…

《生成式AI导论》学习笔记

1.课程定位 2.什么是生成式人工智慧&#xff1f; 3. 今日的生成式人工智慧厉害在哪里&#xff1f; 4.训练不了人工智慧&#xff1f;那我训练自己 5.训练不了人工智慧&#xff1f;你可以训练你自己&#xff08;中&#xff09;——拆解问题使用工具 6.大语言模型修炼史——第一阶…

小程序AI智能名片S2B2C商城系统:解锁内容深耕新境界,助力品牌企业高效定制内容策略

在数字化时代&#xff0c;内容营销已成为品牌企业获取市场份额、增强用户黏性的关键武器。然而&#xff0c;面对海量的互联网信息和复杂多样的社交媒体平台&#xff0c;如何有效地深耕内容&#xff0c;成为众多品牌企业面临的难题。 传统的内容分类与识别方式&#xff0c;往往依…

(三)登录和注册(handle_auto.go)

登录和注册(handle_auto.go) 文章目录 登录和注册(handle_auto.go)一、所需要的结构体信息二、注册三、登录四、退出 一、所需要的结构体信息 type UserAuth struct{}type LoginReq struct {Username string json:"username" binding:"required"Password …

三维图形学知识分享---求平面与模型相交线

在CGAL&#xff08;Computational Geometry Algorithms Library&#xff09;中&#xff0c;Polygon_mesh_processing模块提供了用于处理多边形网格数据结构的功能。其中&#xff0c;surface_intersection函数是用来计算模型的表面相交线的工具。 CGAL_Mesh mesh_orcl;std::vect…

AI大模型探索之路-训练篇1:大语言模型微调基础认知

文章目录 前言一、微调技术概述二、微调的必要性三、大模型的微调方法四、微调过程中的技术细节五、微调后的模型评估与应用总结 前言 在人工智能的广阔研究领域内&#xff0c;大型预训练语言模型&#xff08;Large Language Models, LLMs&#xff09;已经成为推动技术革新的关…

Linux网络—DNS域名解析服务

目录 一、BIND域名服务基础 1、DNS系统的作用及类型 DNS系统的作用 DNS系统类型 DNS域名解析工作原理&#xff1a; DNS域名解析查询方式&#xff1a; 2、BIND服务 二、使用BIND构建域名服务器 1、构建主、从域名服务器 1&#xff09;主服务器配置&#xff1a; 2&…

竞赛课第九周(埃式筛法,矩阵乘法)

1.埃式筛法:求区间[2, n]内所有的素数对 【参考代码】 #include <bits/stdc.h> using namespace std;const int N 1e5; vector<int> prime; bool visit[N];int main() {int n;cin>>n;memset(visit, false, sizeof(visit));for(int i2; i<sqrt(n); i){i…

Datasophon1.2.1集成Dinky1.0.1

Dinky 下载地址: https://github.com/DataLinkDC/dinky/releases/tag/v1.0.1 Dinky 官网&#xff1a;https://www.dinky.org.cn/ 1.下载Dinky wget https://github.com/DataLinkDC/dinky/releases/download/v1.0.1/dinky-release-1.16-1.0.1.tar.gz mv dinky-release-1.16-1.…

分享8款安全监控/日志记录工具

安全监控工具的作用是实时监控和分析系统的安全状态&#xff0c;而日志记录工具的作用主要是记录系统的运行过程及异常信息。 关于安全监控工具&#xff0c;它通过对计算机系统、网络、应用程序和数据进行实时监控和分析&#xff0c;帮助发现和防止安全威胁和攻击。这种监控不…

tcp inflight 守恒算法背后的哲学

tcp inflight 守恒拥塞控制的正确性 很久以前我开始纠结 tcp 锯齿&#xff0c;很多年后我知道这叫 capacity-seeking&#xff0c;甚至说 tcp 属于 capacity-seeking protocol 的原因就是它早已深入人心的 aimd 行为&#xff0c;而该行为生成了 tcp 锯齿。 在消除锯齿&#xf…