c语言预处理指令详解

//extern int ADD(int x, int y);//声明引用外部文件
//c语言预处理
// 文本文件  翻译+链接         二进制文件   运行 
//test.cpp————————》test.exe————————》
// 编译器   翻译环境  链接器             执行环境
//      test.obj(目标文件)
// 
//(linux系统)翻译器:
// gcc -E
// 预编译(test.i):把头文件放进文件里 
//                   删除注释(空格替换)
//                   #define 定义的进行替换
// gcc -S
// 编译(test.s):把c代码翻译成汇编代码
//                 (语法分析,词法分析,语义分析,符号汇总)
// gcc -c
//汇编(test.o):形成符号表
//               把汇编代码转换成二进制代码指令
//               obj文件(目标文件) 二进制文件
// 
// 链接器:
//  多个 .obj 文件通过链接器链接
//  合并段表(符号表):(固定格式分段) elf格式  多个程序分段形成符号表 
//  符号表的合并和重定位: 多个符号表合并,
//                         符号重定位(把一个文件内的声明的符号地址改成
//                          另一个文件的实际有效地址),这样就链接起来了
// 
// 
// 运行环境:
//         程序必须载入内存中:有操作系统就由操作系统完成
//                         独立环境中,程序需要手动安排,或可执行代码置入只读内存
//         程序开始执行,调用main函数
//         开始执行代码,使用一个运行时堆栈(stack),存储函数局部变量和返回地址,
//             同时可以使用静态(static)内存中的变量并在执行过程中一直保留他们的值
//         终止程序,正常终止,或意外终止
//
// 预处理详解:
//     预定义符号: __FILE__ 进行编译的源文件——当前文件的路径
//                  __LINE__ 文件当前的行号——当前代码的行号
//                  __DATE__ 文件被编译的日期
//                  __TIME__ 文件被编译的实际
//                  __STDC__ 如果编译器遵循ANSI C 值为1, 否则未定义
//                  ...
//     预处理指令:
//                #define// 定义的静态值,可在程序中完成替换,不能在内容后面加;
//                #include
//                #pragma pack(4) 设置默认对齐数
//                #pragma pack()
//                #if
//                #endif
//                #error
//                #line
//                #开头定义的指令
//
 

//#define 定义标示符号 #define name stuff  name名字  stuff内容
//#define MAX 100
//#define STR "HEHE"
//#define reg register//存储器关键字
//#define do_forever for(::)//用形象的符号替换一种函数实现
//#define CASE break:case//在case 语句后面自动把break写上
//#define DEBUG_PRINT printf("%s\n", __TIME__)//如果内容过长,每行加上 \ (续航符)


//#define定义宏
//#define机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)
//           定义宏(define macro)
//           #define name(parament-list) stuff    
//           parament-list是参数列表,用逗号隔开
//           参数可以出现在suff里面注:左括号和name紧贴一起
//           stuff内容根据符号优先级用()进行分装
//
// #define 替换规则
// 1;在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号;
//   发现有就进行替换。
// 2,替换文本随后被插入程序中的原文本位置,对于宏,参数名都会被他们的值替换
// 3,最后,再次扫描是否有#define定义的符号,发现有就再次替换
//    注意:
//        1:宏参数和#define可以出去其他#define定义的符号,但是宏不能递归
//        2:预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索
//
// 
// #和##
//    # 字符串常量化运算符  把宏参数插入到字符串中    
//    ## 合并粘贴运算符,可以把它两边的符号合成一个符号,
//       允许宏定义从分离的文本片段创建标识符
//
// 
// 带有副作用的宏参数 
// 
// 函数有参数类型,宏没有参数类型
// 
// #undef 取消宏定义
// 
// 
// 命令行定义
//  在程序执行时,许多编译器提供了允许在命令行中定义符号的功能(给程序中的变量赋值)
// 有的命令行有参数 有的没有
// 
// 
// 条件编译指令
//     选择性的对语句进行编译或者放弃,有条件的编译指令
//    1, #if 常量表达式
//       #endif   ——结束
// 
//    2,#if 常量表达式   ---如果
//       #elif 常量表达式 ——或如果
//       #else 常量表达式 ——否则
//       #endif           ——结束
// 
//    3,判断是否被定义
//       #if defined(symbol)--如果定义了symbol
//       #ifdef symbol 和上一句等价   
//       
//       #if !defined(symbol) --如果没有定义symbol
//       #ifndef symbol 和上一句等价
//       
//       #endif   ---结束
//    4,嵌套指令
//       #if defined(str1)//如果定义了str1
//             #ifdef ptr1//如果定义了ptr1
//                 r1();//执行r1
//             #endif  ---内结束
//             #ifdef ptr2//如果定义了ptr2
//                 r2();执行r2
//             #endif  ---内结束
//       #elif defined(str2)//或如果定义了str2
//             #ifdef ptr2//如果定义了ptr2
//                  r2();//执行r2
//             #endif  ---内结束
//       #endif  ---外结束
// 
//
// 文件包含 #include
//      使另一个文件被编译,拷贝到当前文件里
//       <库函数头文件> 在标准路径(安装路径)去查找
//     "自编(本地)头文件"  
//    查找策略:先查源文件所在目录下找,未发现就在标准位置(安装路径)查找,最后未发现提示编译错误
//   
// 
//    嵌套文件重复包含头文件解决方案
// 方案1, #ifndef __TEST_H__
//        #define __TEST_H__
//        (头文件内容)
//        #endif
// 方案2,#pragma once 
//    

//含参数的宏定义
//#define MAX 100
//#define SQUARE(X) ((X)*(X))//stuff内容根据符号优先级用()进行分装

//#把宏定义参数插入字符串里
//void print(int x)
//{
//    printf("the value of x is %d\n", x);//x是固定的,不能转换a或者b
//}
//#define PRINT(X) printf("the value of "#X" is %d\n", X)//多个字符串放在一起会自动连在一起

//##字符串粘连
//#define CAT(X,Y) X##Y//把X的内容和Y的内容连在一起

//宏定义参数中存在++ -- 等副作用参数
//#define MAX(X,Y) ((X)>(Y)?(X):(Y))  //给X,Y 的变量是直接整体替换的,不会进行计算
//#define 优势:预处理完成替换直接到判断语句,没有函数调用和返回的开销,更省时间,
//        宏没有参数类型(通用),还可以传(类型)参数
//        劣势:宏会直接将代码插入到程序中,如果宏很长,就会增加程序的长度
//              宏不能调试,没参数类型,不严谨
//              宏会有运算符优先级带来的副作用
//函数会有调用和返回的开销,且有函数参数类型要求

//#undef MAX 取消宏定义

//int Max(int x, int y)
//{
//    return (x > y ? x : y);
//}

//#define DEBUG


int main()
{

    int arr[10] = { 0 };
    int i = 0;
    int a = 10;
    int b = 20;
    FILE* pf = fopen("log.txt", "w");
    for (i = 0; i < 10; i++)
    {
        arr[i] = i;
        fprintf(pf, "file:%s line:%d date:%s time:%s i = %d\n",
            __FILE__,__LINE__,__DATE__,__TIME__,i);
    }
    fclose(pf);
    pf = NULL;
    for (i = 0; i < 10; i++)
    {
        printf("%d ", arr[i]);
    }
    int c = ADD(a, b);
    printf("%d", c);
    //printf("%s\n", __FILE__);//当前文件的路径
    //printf("%d\n", __LINE__);//当前代码的行号
    //printf("%s\n", __DATE__);
    //printf("%s\n", __TIME__);
    //printf("%d\n", __STDC__);VS是未定义这个的

    //宏定义参数替换
    int ret = SQUARE(5);//ret = 25;
    ret = SQUARE(5 + 1);//ret = 11;宏是直接用5+1替换X,使用得到11,
    //可以在宏定义用(X)进行分开成单独个体
    ret = SQUARE(MAX);
    printf("MAX= %d\n", MAX);//"MAX= %d\n"中的字符串MAX不会被#define检测替换

    //#把宏参数插入到字符串中
    int a = 10;
    int b = 20;
    print(a);
    print(b);
    PRINT(a);
    printf("the value of "#X" is %d\n", X)
    PRINT(b);

    //##把字符串粘连在一起
    //int abcd10 = 2019;
    //printf("%d\n", CAT(abcd, 10));//abcd##10 == abcd10

    //带有副作用的宏参数
    int a = 10;
    int b = 11;
    int max = MAX(a++, b++);//++改变了a和b的值
    max = ((a++)>(b++)?(a++):(b++))
    // 这个代码执行:先比较a和b b大,然后a++,b++,再把b的赋值给max,最后b++
    printf("%d\n", max);//12
    printf("%d\n", a);//11
    printf("%d\n", b);//13

    //函数和宏比较
    int a = 10;
    int b = 11;
    float c = 3.0f;
    float d = 3.1f;
    int max = MAX(a, b);
    printf("%d\n", max);
    max = Max(a, b);
    printf("%d\n", max);
    float max1 = MAX(c, d);

    //条件编译
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int i = 0;
    for (i = 0; i < 10; i++)
    {
        arr[i] = 0;
#ifdef DEBUG//如果DEBUG定义了,就执行printf
#if defined DEBUG//如果DEBUG定义了,就执行printf
#ifndef DEBUG//如果没有定义DEBUG
#if !defined DEBUG
        printf("%d ", arr[i]);
#endif // DEBUG  结束条件编译

        
    }

#if 1==0
    printf("1\n");
#elif 2==2
    printf("2\n");
#else
    printf("3")

#endif

    return 0;
}

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

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

相关文章

工业边缘计算为什么?

在工厂环境中使用边缘计算并不新鲜。可编程逻辑控制器&#xff08;PLC&#xff09;、微控制器、服务器和PC进行本地数据处理&#xff0c;甚至是微型数据中心都是边缘技术&#xff0c;已经在工厂系统中存在了几十年。在车间里看到的看板系统&#xff0c;打卡系统&#xff0c;历史…

Flowable中间事件-中间信号捕获事件

定义 信号中间事件分为 Catching 事件和 Throwing 事件&#xff0c;即信号中间捕获事件&#xff08;Signal Intermediate Catch Event&#xff09;和信号中间抛出事件&#xff08;Signal Intermediate Throwing Event&#xff09;。 当流程执行到信号中间捕获事件时就会中断在…

什么是ROC曲线

ROC曲线&#xff08;Receiver Operating Characteristic Curve&#xff09;&#xff0c;也称为“接受者操作特性曲线”。它最早应用于雷达信号检测的分析&#xff0c;后来广泛应用于心理学和医学领域。 ROC分析是进行临床诊断试验评价最常用的方法。诊断试验是指评价某种疾病诊…

Xshell配置ssh免密码登录-公钥与私钥登录linux服务器

目录 简介 提示 方法步骤 步骤1&#xff1a;生成密钥公钥&#xff08;Public key&#xff09;与私钥(Private Key) 方法1&#xff1a;使用xshell工具 方法2&#xff1a;使用命令行 步骤2&#xff1a;放置公钥(Public Key)到服务器 方法1&#xff1a;&#xff08;我使用的是…

InnoDB数据存储结构

一. InnoDB的数据存储结构&#xff1a;页 索引是在存储引擎中实现的&#xff0c;MySQL服务器上的存储引擎负责对表中数据的读取和写入工作。不同存储引擎中存放的格式一般不同的&#xff0c;甚至有的存储引擎比如Memory都不用磁盘来存储数据&#xff0c;这里讲讲InooDB存储引擎…

深度学习调参指南

1. 选择合适的模型架构 模型的结构(层数和宽度)&#xff0c;参数配置&#xff0c;尽量用已经有效的模型 2. 选择优化器 针对具体的问题&#xff0c;从选择常用的优化器开始&#xff0c;进行比较 3. 选择BatchSize 1). Batch Size决定训练速度&#xff0c;但是不影响验证集…

WPF实战学习笔记23-首页添加功能

首页添加功能 实现ITodoService、IMemoService接口&#xff0c;并在构造函数中初始化。新建ObservableCollection<ToDoDto>、 ObservableCollection<MemoDto>类型的属性&#xff0c;并将其绑定到UI中修改Addtodo、Addmemo函数&#xff0c;将添加功能添加 添加添加…

NineData支持最受欢迎数据库PostgreSQL

根据在 Stack Overflow 发布的 2023 开发者调研报告中显示&#xff0c;PostgreSQL 以 45% vs 41% 的受欢迎比率战胜 MySQL&#xff0c;成为新的最受欢迎的数据库。NineData 也在近期支持了 PostgreSQL&#xff0c;用户可以在 NineData 平台上进行创建数据库/Schema、管理用户与…

解决AttributeError: ‘DataParallel‘ object has no attribute ‘xxxx_fc1‘

问题描述 训练模型时&#xff0c;分阶段训练&#xff0c;第二阶段加载第一阶段训练好的模型的参数&#xff0c;接着训练 第一阶段训练&#xff0c;含有代码 if (train_on_gpu):if torch.cuda.device_count() > 1:net nn.DataParallel(net)net net.to(device)第二阶段训练…

Linux环境Arduino IDE中配置ATOM S3

linux选择ubuntu发行版。 硬件设备有多小呢&#xff1a; 功能超级强大。 之前的ROS1和ROS2案例已经全部移植完成并测试结束&#xff08;三轮纯人力校验&#x1f60e;&#xff09;。 官网文档信息非常非常好&#xff1a; https://docs.m5stack.com/zh_CN/quick_start/atoms3…

Jenkins 配置maven和jdk

前提:服务器已经安装maven和jdk 一、在Jenkins中添加全局变量 系统管理–>系统配置–>全局属性–>环境变量 添加三个全局变量 JAVA_HOME、MAVEN_HOME、PATH 二、配置maven 系统管理–>全局工具配置–>maven–>新增 新增配置 三、配置JDK 在系统管…

java策略模式

在Java中&#xff0c;策略模式&#xff08;Strategy Design Pattern&#xff09;用于定义一系列算法&#xff0c;并将每个算法封装成单独的类&#xff0c;使得它们可以互相替换&#xff0c;让客户端在使用算法时不需要知道具体的实现细节。策略模式是一种行为型设计模式&#x…

科普 | OSI模型

本文简要地介绍 OSI 模型 1’ 2’ 3。 更新&#xff1a;2023 / 7 / 23 科普 | OSI模型 术语节点链路协议网络拓扑 概念作用结构应用层表示层会话层传输层网络层数据链路层物理层 数据如何流动OSI 和TCP/IP 的对应关系和协议参考链接 术语 节点 节点&#xff08; Node &#…

Go 语言切片是如何扩容的?

在 Go 语言中&#xff0c;有一个很常用的数据结构&#xff0c;那就是切片&#xff08;Slice&#xff09;。 切片是一个拥有相同类型元素的可变长度的序列&#xff0c;它是基于数组类型做的一层封装。它非常灵活&#xff0c;支持自动扩容。 切片是一种引用类型&#xff0c;它有…

SRS源码框架,日志记录SrsFileLog的使用

本章内容解读SRS开源代码框架&#xff0c;无二次开发&#xff0c;以学习交流为目的。 SRS是国人开发的开源流媒体服务器&#xff0c;C语言开发&#xff0c;本章使用版本&#xff1a;https://github.com/ossrs/srs/tree/5.0release。 目录 SRS日志记录源码源码测试 SRS日志记录…

querySubObject(“Cells(int,int)“, j,i)->property(“Value“)读不到数据问题

在使用qt读取Excel文件内容的时候&#xff0c;使用下列方式&#xff1a; worksheet->querySubObject("Cells(int,int)", j,i)->property("Value").toString(); 不会报错&#xff0c;但读取不到数据。多次尝试发现应该将property改为dynamicCall 下…

前端(九)——探索微信小程序、Vue、React和Uniapp生命周期

&#x1f642;博主&#xff1a;小猫娃来啦 &#x1f642;文章核心&#xff1a;探索微信小程序、Vue、React和Uniapp生命周期 文章目录 微信小程序、Vue、React和Uniapp的基本定义和应用领域微信小程序生命周期生命周期概述页面生命周期应用生命周期组件和API的生命周期钩子 Vu…

【雕爷学编程】MicroPython动手做(16)——掌控板之图片图像显示

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…

基于注解的 SpringMVC

SpringMVC SpringMVC使用SpringMVC的两个配置EnableWebMVC 和 ACWACSpringMVC执行流程接收请求参数Postman 发包工具&#xff08;&#xff09;get 请求---简单类型数据&#xff08;基本数据类型和String&#xff09;get 请求---对象类型数据get 请求---数组类型get 请求 --- 集…

Python自动计算Excel数据指定范围内的区间最大值

本文介绍基于Python语言&#xff0c;基于Excel表格文件内某一列的数据&#xff0c;计算这一列数据在每一个指定数量的行的范围内&#xff08;例如每一个4行的范围内&#xff09;的区间最大值的方法。 已知我们现有一个.csv格式的Excel表格文件&#xff0c;其中有一列数据&#…