C语言16--宏定义和关键字

news2024/11/15 10:03:39

预处理

        在C语言程序源码中,凡是以井号(#)开头的语句被称为预处理语句,这些语句严格意义上并不属于C语言语法的范畴,它们在编译的阶段统一由所谓预处理器(cc1)来处理。所谓预处理,顾名思义,指的是真正的C程序编译之前预先进行的一些处理步骤,这些预处理指令包括:

  1. 头文件:#include
  2. 定义宏:#define
  3. 取消宏:#undef
  4. 条件编译:#if、#ifdef、#ifndef、#else、#elif、#endif
  5. 显示错误:#error
  6. 修改当前文件名和行号:#line
  7. 向编译器传送特定指令:#progma
  • 基本语法
    • 一个逻辑行只能出现一条预处理指令,多个物理行需要用反斜杠 \ 连接成一个逻辑行
    • 预处理是整个编译全过程的第一步:预处理 - 编译 - 汇编 - 链接
    • 可以通过如下编译选项 ( -E )来指定来限定编译器只进行预处理操作:
gcc example.c -o example.i -E

宏的概念

宏(macro)实际上就是一段特定的字串,在源码中用以替换(无脑)为指定的表达式。例如:

#define PI 3.14

此处,PI 就是宏(宏一般习惯用大写字母表达,以区分于变量和函数,但这并不是语法规定,只是一种习惯),是一段特定的字串,这个字串在源码中出现时,将被替换为3.14。例如:

int main()
{
    printf("圆周率: %f\n", PI); 
    // 此语句将被替换为:printf("圆周率: %f\n", 3.14);
}
  • 宏的作用:
    • 使得程序更具可读性:字串单词一般比纯数字更容易让人理解其含义。
    • 使得程序修改更易:修改宏定义,即修改了所有该宏替换的表达式。
    • 提高程序的运行效率:程序的执行不再需要函数切换开销,而是就地展开。

无值宏定义

定义宏的时候,不一定需要带值,无值的宏定义经常在条件编译中作为判断条件出现,例如:

#define BIG_ENDIAN
#define __cplusplus

无参(参数)宏

无参宏意味着使用宏的时候,无需指定任何参数,比如:

#define PI          3.14
#define SCREEN_SIZE 800*480*4 
int main()
{
    // 在代码中,可以随时使用以上无参宏,来替代其所代表的表达式:
    printf("圆周率: %f\n", PI); 
    mmap(NULL, SCREEN_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, ...);
}

注意到,上述代码中,除了有自定义的宏,还有系统预定义的宏:

// 自定义宏:
#define PI          3.14
#define SCREEN_SIZE 800*480*4 

// 系统预定义宏
#define NULL ((void *)0)
#define PROT_READ    0x1    /* Page can be read.  */
#define PROT_WRITE    0x2    /* Page can be written.  */
#define MAP_SHARED    0x01    /* Share changes.  */

宏的最基本特征是进行直接文本替换,以上代码被替换之后的结果是:

int main()
{
    printf("圆周率: %f\n", 3.14); 
    mmap(((void *)0), 800*480*4, 0x1|0x2, 0x01, ...);
}

带参宏

带参宏意味着宏定义可以携带“参数”,从形式上看跟函数很像,例如:

#define MAX(a, b)   a>b ? a : b
#define MIN(a, b)   a<b ? a : b

以上的MAX(a,b) 和 MIN(a,b) 都是带参宏,不管是否带参,宏都遵循最初的规则,即宏是一段待替换的文本,例如在以下代码中,宏在预处理阶段都将被替换掉:

int main()
{
    int x = 100, y = 200;
    printf("最大值:%d\n", MAX(x, y));
    printf("最小值:%d\n", MIN(x, y));
    // 以上代码等价于:
    // printf("最大值:%d\n", x>y ? x : y);
    // printf("最小值:%d\n", x<y ? x : y);
}

带参宏的特点:

    1. 直接文本替换,不做任何语法判断,更不做任何中间运算。
    2. 宏在编译的第一个阶段就被替换掉,运行中不存在宏。
    3. 宏将在所有出现它的地方展开,这一方面牺牲了内存空间,另一方面有节约了切换时间。

带参宏的副作用

由于宏仅仅做文本替换,中间不涉及任何语法检查、类型匹配、数值运算,因此用起来相对函数要麻烦很多。例如:

#define MAX(a, b) a>b ? a : b

int main()
{
    int x = 100, y = 200;
    printf("最大值:%d\n", MAX(x, y==200?888:999));
}

直观上看,无论 y 的取值是多少,表达式 y==200?888:999 的值一定比 x 要大,但由于宏定义仅仅是文本替换,中间不涉及任何运算,因此等价于:

printf("最大值:%d\n", x>y==200?888:999 ? x : y==200?888:999);

可见,带参宏的参数不能像函数参数那样视为一个整体,整个宏定义也不能视为一个单一的数据,事实上,不管是宏参数还是宏本身,都应被视为一个字串,或者一个表达式,或者一段文本,因此最基本的原则是:

#define MAX(a, b) ((a)>(b) ? (a) : (b))

typedef、extern和define关键字的详细总结:

static关键字

  • 作用:在C语言中,static关键字有多种用途,它可以用于函数、变量和全局变量。
  • static修饰局部变量:使之由栈内存临时数据,变成了静态数据(存储与数据段)。
  • static修饰全局变量:使之由各文件可见的静态数据,变成了本文件可见(缩小可见范围、降低同名冲突的概率)的静态数据。
  • static修饰函数:使之由各文件可见的函数,变成了本文件可见(缩小可见范围、降低同名冲突的概率)的静态函数。

const关键字

  • const型指针有两种形式:①常指针 ②常目标指针
  1. 常指针:const修饰指针本身,表示指针变量本身无法修改。
  2. 常目标指针:const修饰指针的目标,表示无法通过该指针修改其目标。
  3. const修饰变量,变量的值修饰为常量不可修改

typedef关键字

  • 作用:typedef关键字用于创建类型的别名,可以为现有的数据类型定义一个新的名字。
    • typedef int int32_t; // 将类型 int 取个别名,称为 int32_t
    • typedef long int64_t;// 将类型 long 取个别名,称为 int64_t

extern关键字

  • 作用:extern关键字用于声明一个变量或函数是在其他文件中定义的。
  • 使用方法:在一个文件中使用extern关键字声明一个变量或函数,表示该变量或函数是在其他文件中定义的。
  • 注意事项:使用extern关键字声明的变量或函数在当前文件中并不分配存储空间,只是告诉编译器该变量或函数在其他文件中定义。

结语:

        在这篇博客中,我们深入探讨了 C 语言中的宏定义与关键字的运用和特点。宏定义作为预处理器指令,为代码提供了灵活性与可维护性,使得程序员能够轻松地创建复杂的表达式、常量以及代码块。同时,C 语言的关键字则是我们构建程序逻辑的基石,它们定义了语言的语法规则和结构,确保代码的正确性和可读性。

        理解宏定义与关键字不仅有助于提高我们的编程技巧,还能让我们更有效地优化和简化代码。作为 C 语言程序员,掌握这些元素使我们能更加高效地应对各种编程挑战,并提升解决问题的能力。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

有没有视频加字幕免费软件?值得收藏的10款字幕编辑软件推荐!

随着视频成为我们生活中不可或缺的一部分&#xff0c;它已然成为信息传播的重要方式。然而&#xff0c;仅有精彩的内容还不足以吸引全球观众&#xff0c;字幕的加入显得尤为重要。不仅能帮助不同语言的用户理解视频内容&#xff0c;还能提升视频的互动性。许多视频制作爱好者开…

Linux 防火墙:iptables (一)

文章目录 iptables 概述netfilter 与 iptables 的关系 四表五链规则表规则链数据包处理的优先顺序与规则链匹配顺序规则表的优先顺序规则链的匹配顺序规则链内的匹配顺序匹配流程示意图 安装与格式iptables 的安装iptables 防火墙的配置方法iptables 命令行配置方法常用的控制类…

20道经典自动化测试面试题【建议收藏】

概述 觉得自动化测试很难&#xff1f; 是的&#xff0c;它确实不简单。但是学会它&#xff0c;工资高啊&#xff01; 担心面试的时候被问到自动化测试&#xff1f; 嗯&#xff0c;你担心的没错&#xff01;确实会被经常问到&#xff01; 现在应聘软件测试工程师的岗位&…

圆锥曲线练习

设 A ( x 1 , y 1 ) , B ( x 2 , y 2 ) A\left( x_{1}, y_{1} \right), B\left( x_{2}, y_{2} \right) A(x1​,y1​),B(x2​,y2​) l : y k ( x 2 ) l: y k\left( x2 \right) l:yk(x2) 显然 y 0 y0 y0符合题意 当 k ≠ 0 k\neq 0 k0 联立 l l l和 C C C ( k 2 1 2 ) x…

基于SpringBoot+Vue+MySQL的校园周边美食探索及分享平台

系统背景 在当今数字化时代&#xff0c;校园生活正日益融入信息技术的浪潮之中&#xff0c;学生们对于便捷、高效且富有趣味性的生活方式有着越来越高的追求。特别是在饮食文化方面&#xff0c;随着校园周边餐饮业态的日益丰富&#xff0c;学生们渴望一个能够集美食探索、分享与…

SpringBoot入门(黑马)

1. SpringBootWeb入门开发 需求&#xff1a;使用SpringBoot 开发一个web 应用&#xff0c;浏览器发起请求 /hello 后&#xff0c;给浏览器返回字符串"Hello World~"。 步骤&#xff1a; 1. 创建springBoot工程&#xff0c;并勾选web开发相关依赖。 2. 定义 HelloCo…

iOS——strong和copy的底层实现

copy和strong的区别 有如下代码&#xff1a; #import "Person.h"interface Person ()property (nonatomic, strong) NSString *strStrong; property (nonatomic, copy) NSString *strCopy;endimplementation Person- (void) go {NSMutableString *newStr [NSMutab…

【前端】 flex布局详解

Flex布局开启&#xff0c;在编写之前&#xff0c;我们要先搞清楚一个问题&#xff0c;就是你要让谁开启flex布局&#xff1f;我们要开启flex布局的最终目的一定是为了让某几个元素进行规范化布局&#xff0c;那如果你单独写在某个元素身上&#xff0c;那它的兄弟元素也不知道自…

【FPGA XDMA AXI Bridge 模式】PCIe:BARs 和 AXI:BARs 含义解析

XDMA IP核两种模式 Xilinx的 DMA/Bridge Subsystem for PCI Express IP核中&#xff0c;支持普通的XDMA模式&#xff0c;但是这种模式只允许主机端发起PCIe 读写请求&#xff0c;FPGA内部无法主动发起读写请求&#xff0c;也即FPGA无法主动读写HOST的内存。 而该IP核的另一种…

超分论文ESPCN解读

论文地址&#xff1a;Real-Time Single Image and Video Super-Resolution Using an Efficient Sub-Pixel Convolutional Neural Network 相关知识点总结&#xff1a; 许多SR技术的一个关键假设是&#xff0c;大部分高频数据是冗余的&#xff0c;因此可以从低频分量中准确重建…

IIC时序(通俗易懂版,嘎嘎简单)

介绍 简述&#xff1a;IIC总线就是一个两根线的规则&#xff08;半双工&#xff09;&#xff0c;规定通信双方如何传送数据&#xff0c;至于传送数据&#xff0c;无非就是主机给从机发送数据&#xff0c;或者从机给主机发送数据&#xff0c;其中加了一点发过去的数据有没有回应…

佰朔资本:大宗交易是什么?出现大宗交易意味着什么?

大宗生意&#xff0c;又叫作大宗生意&#xff0c;是指抵达规则的最低限额的证券单笔生意申报&#xff0c;生意两边经过协议达到共同并经生意所招认成交的证券生意。 出现大宗生意&#xff0c;说明该股票的整体体现弱于商场均匀体现&#xff0c;且主力正在减仓或许出货。大宗生…

charles使用ssl证书抓包https请求失败解决方案

前提 手机必须有root权限&#xff0c;并且是使用Magisk&#xff08;面具&#xff09;进行root; ssl证书安装 安卓7.0以下的手机&#xff0c;ssl证书是直接安装到了‘系统证书’里&#xff0c;可以直接抓取https请求&#xff0c;但是目前的手机大部分都是7.0以上的&#xff1…

第17章.RCC-STM32时钟配置

目录 0. 《STM32单片机自学教程》专栏 17.1 STM32时钟树 17.1.1 时钟源 17.1.2 锁相环PLL 17.1.3 系统时钟 17.1.3.1 系统时钟SYSCLK 17.1.3.2 AHB/APB总线时钟 17.1.3.3 其他时钟 17.1.3.4 MCO 时钟输出 17.2 系统时钟库函数 17.3 系统时钟配置练习 …

Python基础语法(1)上

常量和表达式 我们可以把 Python 当成一个计算器&#xff0c;来进行一些算术运算。 print(1 2 - 3) print(1 2 * 3) print(1 2 / 3) 这里我们可能会有疑问&#xff0c;为什么不是1.6666666666666667呢&#xff1f; 其实在编程中&#xff0c;一般没有“四舍五入”这样的规则…

C++入 门——“多态”

一、多态 多态是面向对象的一个重要特性&#xff0c;它允许程序在运行时通过传入不同对象而呈现出不同的运行结果&#xff0c;比如同样的采访&#xff0c;询问老师的年龄和学生的年龄最后得到的结果是不一样的&#xff0c;这就呈现出一种多态。 多态分为两种&#xff1a;静态多…

鸿蒙OpenHarmony【轻量系统芯片移植】内核移植

移植芯片架构 芯片架构的移植是内核移植的基础&#xff0c;在OpenHarmony中芯片架构移植是可选过程&#xff0c;如果当前OpenHarmony已经支持对应芯片架构则不需要移植操作&#xff0c;在“liteos_m/arch”目录下可看到当前已经支持的架构&#xff0c;如表1&#xff1a; 表1 …

2024年全国大学生软件测试大赛赛项安排(一)

✨博客主页&#xff1a; https://blog.csdn.net/m0_63815035?typeblog &#x1f497;《博客内容》&#xff1a;.NET、Java.测试开发、Python、Android、Go、Node、Android前端小程序等相关领域知识 &#x1f4e2;博客专栏&#xff1a; https://blog.csdn.net/m0_63815035/cat…

怎么选择靠谱AI论文生成工具?看完我的试用都会明白!

2024年上半年开始AI论文写作工具开始火了&#xff0c;层出不穷&#xff01;作为一个经常需要写论文的懒人&#xff0c;我非常好奇这些AI工具的实际效果到底怎么样&#xff1f;为了测试不同工具的实力&#xff0c;我对他们都进行了试用&#xff0c;发现了一些意想不到的结果....…

【楚怡杯】职业院校技能大赛 “云计算应用” 赛项样题一

某企业根据自身业务需求&#xff0c;实施数字化转型&#xff0c;规划和建设数字化平台&#xff0c;平台聚焦“DevOps开发运维一体化”和“数据驱动产品开发”&#xff0c;拟采用开源OpenStack搭建企业内部私有云平台&#xff0c;开源Kubernetes搭建云原生服务平台&#xff0c;选…