c语言 预处理

news2024/11/20 7:16:46
int main()
{
	//printf("%s\n", __FILE__);//打印所在文件夹位置
	//printf("%d\n", __LINE__);//打印当前所在行号
	//printf("%s\n", __DATE__);//打印当前系统日期
	//printf("%s\n", __TIME__);//时间
	//printf("%s\n", __FUNCTION__);//他所在当前函数的函数名 打印结果为main


	return 0;
}

如何使用以上预处理命令 如下

int main()
{
	//printf("%s\n", __FILE__);//打印所在文件夹位置
	//printf("%d\n", __LINE__);//打印当前所在行号
	//printf("%s\n", __DATE__);//打印当前系统日期
	//printf("%s\n", __TIME__);//时间
	//printf("%s\n", __FUNCTION__);//他所在当前函数的函数名 打印结果为卖弄
	int i = 0;
	FILE* pf = fopen("log.txt", "a+");//以追加的形式是写入  可以应用日志
	if (pf == NULL)
	{
		perror("fopen\n");
		return 1;
	}
	for (i = 0; i < 10; i++)
	{
		fprintf(pf, "%s %d %s %s %d\n", __FILE__, __LINE__, __DATE__, __TIME__, i);
	}
	fclose(pf);
	pf = NULL;

	//printf("%d\n", __STDC__);//编译器支持ansi标准就可以编译出结果。      vs不支持  如果支持编译结果为1(linux)
	return 0;
}

define

define 定义符号

//#define 是定义符号的

#define M 1000//怎么工作。在预处理阶段就把下面的M改成了1000
#define reg register//相当于重赋名了 以后register都可以用reg代替
#define do_forever for(;;)//相当于前面的内容被转换为后面的for(;;)



int main()
{
	reg int num = 0;
	do_forever;//如果想写一个死循环直接这样写就行
	int m = M;
	printf("%d\n", m);

	return 0;
}

#define CASE break;case//定义了一个CASE 他的内容是break;case
int main()
{
	int n = 0;

	switch (n)
	{
	case 1://第一个不能替换
	CASE 2:
	CASE 3:
	}

	return 0;
}

在这里插入图片描述

define 定义宏

在这里插入图片描述
宏的申明:#define name(parament-list)stuff
其中parament-list是一个由逗号隔开的符号表,他们可能出现在stuff中
()里是参数列表 后面的stuff是我们的内容。 前面的参数可以替换到我们的内容里去。

注意:参数列表的左括号必须与name紧邻。
上面的什么意思举例如下

#define 定义宏
括号很重要
#define SQUARE(x) x*x

int main()
{

	printf("%d", SQUARE(3));//结果为9
		printf("%d\n", SQUARE(3+1));//结果为7
			printf("%d\n", 3 + 1 * 3 + 1);  上面为什么   因为宏是完成替换的  替换过来就像左边所写的一样


	return 0;
}
#define SQUARE(X) ((X)*(X))加上括号这样的得出的结果才是想要的4×4=16

#define DOUBLE(X) ((X)+(X))

int main()
{
	printf("%d\n", SQUARE(3+1));//
	printf("%d\n", 10 * DOUBLE(4));

	printf("%d\n", 10 * ((4) + (4)));运算结果为80
	printf("%d\n", 3 + 1 * 3 + 1);
	printf("%d\n", 3 * 3);
	return 0;
}

#define 替换规则

在这里插入图片描述

#define M 100

#define MAX(X, Y) ((X)>(Y)?(X):(Y))

int main()
{
	int max = MAX(101, M);
	//int max = MAX(101, 100);//上面第一条的意思  直接替换后就是这样的

	printf("M = %d\n", M);//注意的第二条   这个表达式中前面的“M=%d”这里面的M不会被替换

	return 0;
}

#和##

#可以把一个参数插入到字符串中

void print(int x)
{
	printf("the value of c is %d\n", x);//发现函数的方式做不到  of后面的不能更改
}
int main()
{
	//printf("hello world\n");
	//printf("hello " "world\n");这两个打印出来的结果一致

	int a = 10;
	print(a);
	//the value of a is 10  希望能打印出这样的一句话

	int b = 20;
	print(b);
	//the value of b is 20

	int c = 30;
	print(c);
	//the value of c is 30

	return 0;
}

接下来我们尝试用宏的方式实现
在这里插入图片描述
以上就是#号的用处。不加#号是替换 加上之后就变成了内容所对应的字符串
它会变成这样// //printf(“the value of ““a”” is %d\n”, a);

#define print(X) printf("the value of "#X" is %d\n", X);
int main()
{
	//printf("hello world\n");
	//printf("hello " "world\n");

	int a = 10;
	print(a);
	//the value of a is 10  

	int b = 20;
	print(b);
	//the value of b is 20

	int c = 30;
	print(c);
	//the value of c is 30

	return 0;
}

按以上代码运行后可得到想要的结果。接下来把他变得更完善些

#define PRINT(X, FORMAT) printf("the value of "#X" is "FORMAT"\n", X);

int main()
{
	//printf("hello world\n");
	//printf("hello " "world\n");

	int a = 10;
	PRINT(a, "%d");
	//printf("the value of ""a"" is %d\n", a);
	//the value of a is 10

	int b = 20;
	PRINT(b, "%d");
	//printf("the value of ""b"" is %d\n", b);

	//the value of b is 20

	int c = 30;
	PRINT(c, "%d");
	//the value of c is 30

	float f = 5.5f;
	PRINT(f, "%f");
	printf("the value of ""F"" is ""%f""\n", f);


	return 0;
}

##如下

在这里插入图片描述

#define CAT(X,Y,Z) X##Y##Z

int main()
{
	int class101101 = 100;
	printf("%d\n", CAT(class, 101, 101));//##作用就是把他么当作一个符号class101101所以这个打印结果为100

	

	return 0;
}

带副作用的宏参数

在这里插入图片描述

#define MAX(X, Y) ((X)>(Y)?(X):(Y))  求两数的较大值

int main()
{
	int a = 5;
	int b = 8;
	int m = MAX(a++, b++);
	//int m=((a++) > (b++) ? (a++) : (b++));  为什么结果为9  就是因为define定义需要先替换。
	printf("m=%d\n", m);

	return 0;
}//输出结果为9   符号的简单替换,不要当成函数,就是符号替换   define先于计算

宏和函数的对比

在这里插入图片描述
求两数的较大值 选择1的话效率更高些 原因有以下两种
在这里插入图片描述
在这里插入图片描述
**与类型无关,所以宏更方便 **

宏的劣势

在这里插入图片描述
以下是宏可以做到但是函数做不到的例子

#define MALLOC(num, type) (type*)malloc(num*sizeof(type)) //(type*)这是返回类型。malloc(num*sizeof(type))这是宏体

int main()
{
	//malloc(10*sizeof(int)); 开辟函数空间。这样写比较麻烦 想写成下面那样 但是语法不支持 但是我们可以用宏定义一个
	//malloc(10, int);
	int*p = MALLOC(10, int);

	//(int*)malloc(10 * sizeof(int));  上面的会被替换成这样
	return 0;
}

在这里插入图片描述
在这里插入图片描述
总结:简单用宏,复杂用函数

命令约定

在这里插入图片描述

#undef(取消定义)

在这里插入图片描述

#define M 100
int main()
{
	int a = M;
#undef M//没加这个之前结果为100  加了后报错  因为加了后相当于 没有了之前的定义
	printf("%d\n", M);

	return 0;
}

命令行参数

命令行可以定义参数
在这里插入图片描述
比如以下代码在vs中会报错 报错原因是m未定义。但是在linux中编译的时候在命令行后定义m参数就可以执行

int main()
{
    int arr[M] = { 0 };
    int i = 0;

    for (i = 0; i < M; i++)
    {
        arr[i] = i;
    }

    for (i = 0; i < M; i++)
    {
        printf("%d ", i);
    }

    return 0;
}

在这里插入图片描述

条件编译

在这里插入图片描述

int main()
{
#ifdef  PRINT 
	printf("hehe\n");
#endif
	return 0;

}//输出结果为空

如果最上面定义了如下

#define PRINT
int main()
{
#ifdef  PRINT 
	printf("hehe\n");
#endif
	return 0;

}//输出结果为hehe

常见的的条件编译指令

在这里插入图片描述

int main()
{
#if 0//常量表达式  0为假  1为真。为假就不执行
	printf("hehe\n");
#endif
	return 0;

}

以下写法也可以

#define PRINT 1

int main()
{

#if PRINT
	printf("hehe\n");
#endif

	return 0;
}

在这里插入图片描述

int main()
{
#if 1==1//打印结果为hehe 因为只要第一个为真后面的不会参与运算了
	printf("hehe\n");
#elif 2==2
	printf("haha\n");
#else 
	printf("heihei\n");
#endif

	return 0;
}

在这里插入图片描述

#define TEST 0
#define HEHE 1

int main()
{
//如果TEST定义了,下面参与编译
//1
#ifdef TEST
	printf("test1\n");
#endif
//2
#if defined(TEST)//与上面的意义相同
	printf("test2\n");
#endif

//如果HEHE不定义,下面参与编译
//3
#ifndef HEHE
	printf("hehe1\n");
#endif
//4
#if !defined(HEHE)
	printf("hehe2\n");
#endif
	return 0;
}

在这里插入图片描述

头文件包含

在这里插入图片描述
//库文件包含,C语言库中提供的函数的头文件使用<>
#include <stdio.h>
//本地文件包含,自定义的函数的头文件使用""
#include “add.h”
//<> 和 ""包含头文件的本质区别是:查找的策略的区别
在这里插入图片描述

//“” 1. 自己代码所在的目录下查找,2.如果第1不找不到,则在库函数的头文件目录下查找
//<> 直接去库函数头文件所在的目录下查找
vs环境标准头文件的路径
//VS2022C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt
//**

嵌套文件包含

在这里插入图片描述

如何防止头文件被包含两次
加#pragma once
在这里插入图片描述
第一句的意思是 如果没由包含 为真的话就会执行下面的一次。如果为假就停止

在这里插入图片描述
防止头文件被重复多次的包含

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

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

相关文章

分享155个ASP源码,总有一款适合您

ASP源码 分享155个ASP源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c; 154个ASP源码下载链接&#xff1a;https://pan.baidu.com/s/12oYeESSXJCd32n463LBt4w?pwd5i1n 提取码&#x…

Java线程池中的execute和submit

一、概述 execute和submit都是线程池中执行任务的方法。 execute是Executor接口中的方法 public interface Executor {void execute(Runnable command); }submit是ExecuteService接口中的方法。 public interface ExecutorService extends Executor {<T> Future<T…

vue+element模仿腾讯视频电影网站(二),增加视频播放详情页

一.前言 1. 本项目在线预览&#xff1a;点击访问 2. 作者其他博客成品汇总预览&#xff1a;点击访问 3. 接上一篇&#xff1a;《vueelement模仿腾讯视频电影网站》 暂时源码并没有提供其他获取渠道&#xff0c;私聊作者获取即可&#xff0c;或通过博客后面名片添加作者&#…

【SSM】Mybatis小技巧汇总

Mybatis技巧一&#xff1a;#{} 和 ${} 的区别使用 ${} 特例一&#xff08;排序&#xff09;使用 ${} 特例二&#xff08;表连接&#xff09;使用 ${} 特例三&#xff08;批量删除&#xff09;技巧二&#xff1a;typeAliases 别名机制别名 Alias 性质技巧三&#xff1a;mappersm…

串级PID控制原理-1

串级计算机控制系统的典型结构如图1所示&#xff0c;系统中有两个PID控制器&#xff0c;Gc2(s)称为副调节器传递函数&#xff0c;包围Gc2(s)的内环称为副回路。Gc1(s)称为主调节器传递函数&#xff0c;包围Gc1(s)的外环称为主回路。主调节器的输出控制量u1作为副回路的给定量R2…

Vuex基本概念

一、基本概念vuex&#xff1a;为了解决不关联的组件整个网站状态数据共享问题&#xff0c;专为Vue.js开发的状态管理模式。采用集中式存储管理应用的所有组件状态&#xff0c;并以相应的规则保证状态以一种可预测的方式发生变化。vuex有5个主要成员&#xff1a;state&#xff1…

DAMA数据管理知识体系指南之数据架构管理

第4章 4.1 简介 数据架构管理是定义和维护如下规范的过程&#xff1a; 提供标准的、通用的业务术语/辞典。 表达战略性的数据需求。 为满足如上需求&#xff0c;概述高层次的整合设计。 使企业战略和相关业务架构相一致。 数据架构是用于定义数据需求、指导对数据资产的整合和…

【C++】从0到1入门C++编程学习笔记 - 提高编程篇:STL常用容器(vector容器)

文章目录一、vector基本概念二、vector构造函数三、vector赋值操作四、vector容量和大小五、vector插入和删除六、vector数据存取七、vector互换容器八、vector预留空间一、vector基本概念 功能&#xff1a; vector数据结构和数组非常相似&#xff0c;也称为单端数组 vector…

Discord多账号抢白名单,如何避免账号关联被封号?

相信玩NFT项目的都不会对Discord陌生&#xff0c;现在NFT的项目都会开Discord伺服器&#xff0c;并且将内容公告在上面、在伺服器里互动&#xff0c;所以如果你想参与NFT的世界&#xff0c;学会使用Discord是一件非常重要的事情。 东哥前2天也出了关于discord如何使用、如何抢白…

很多网站、APP 前段时间一下都变灰了。 先来感受一下变灰后的效果。

很多网站、APP 前段时间一下都变灰了。 先来感受一下变灰后的效果。 这种灰色的效果怎么实现的呢&#xff1f;如何做到图片、文字、按钮都变灰的效果呢&#xff1f; 方案 1&#xff0c;换一套灰色的 UI&#xff0c;那显然成本太大了&#xff0c;用脚指头想一想就知道不太可能…

C语言---选择排序和堆排序

文章目录前言一、简单选择排序1.简介2.算法思路3.代码实现二、堆排序1.简介2.算法思路3.代码实现总结前言 堆排序是选择排序的一种&#xff0c;今天我们讲解一下堆排序和简单选择排序 一、简单选择排序 1.简介 选择排序&#xff08;Selection sort&#xff09;是一种简单直观…

ZoomCharts JavaScript 1.20.2 Crack

深入探索数据 令人惊叹的数据可视化方式 - 这里是 ZoomCharts JavaScript 图表的不同交互可能性和功能。 内容向下钻取和向上钻取 深入研究特定数据点或获得更大的图景。通过放大或缩小与图表进行物理交互&#xff0c;浏览不同的数据级别。 数据过滤 选择一个或多个数据点查看具…

【软件测试面试】他凭什么能在面试中狂揽10个offer?

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 小高&#xff1a; 记…

2023年屏蔽iOS16系统更新,去除小红点,最新方法

昨天开始&#xff0c;屏蔽iOS系统更新的旧文件已经过期&#xff0c;许多老粉收到了更新提醒&#xff0c;因此现在给大家带来最新的屏蔽文件 这个文件可以屏蔽iOS系统更新和提醒&#xff0c;防止手机自动下载更新。 这个方法支持所有 iPhone 和 iPad&#xff0c;支持所有 iOS 和…

# Android未来几年发展规划【纵横发展】

前言 如果你是移动开发人员&#xff0c;那么首先要跟上技术的最新发展趋势&#xff0c;并时刻关注新事物&#xff0c;即使有时你甚至需要质疑自己的信仰。应用开发人员一方面一直在努力想办法简化和缩短开发过程&#xff0c;另一方面也在努力构建最佳的设计和用户体验。每年我…

【MPP数据库】StarRocks分区、分桶探索与实践

1.先学习一下StarRocks的架构图&#xff1a; 2.基本概念 2.1 Row & Column 一张表包括行&#xff08;Row&#xff09;和列&#xff08;Column&#xff09;。Row 即用户的一行数据。Column 用于描述一行数据中不同的字段。 Column 可以分为两大类&#xff1a;Key 和 Value…

leetcode刷题记录总结-7.递归回溯算法(进行中)

文章目录零、回溯算法理论总览什么是回溯法回溯法的效率回溯法解决的问题如何理解回溯法回溯法模板一、组合问题[77. 组合](https://leetcode.cn/problems/combinations/)题解递归实现组合型枚举&#xff1a;每个点选与不选子集问题模板组合问题解决思路回溯思路&#xff1a;遍…

GAMES101笔记:辐射度量学(上)

Radiometry 辐射度量学 如何描述光照&#xff0c;定义了一系列的方法和单位准确度量光的空间属性&#xff1a; Radiant fluxintensityirradianceradiance 以物理正确的方式进行光照计算 Radiant Energy and Flux (Power) Radiant Energy 定义 Radiant Energy 是电磁辐射的能…

6、数据的合并

目录 一、添加变量即横向合并。 二、添加个案即纵向合并 在实际工作中&#xff0c;为了提高效率&#xff0c;经常需要将一份数据分成几部分分别录入&#xff0c;或为了便于分析&#xff0c;又将几个数据文件合并成一个总的数据文件。为此&#xff0c;SPSS提供了两种合并数据文…

【7】【vue】【vue3】

1、项目结构&#xff1a; asserts用来存放静态资源的&#xff08;一些图片&#xff0c;公共的css文件等&#xff09; components用来存放vue的组件&#xff08;vue是组件开发&#xff09; App.vue是主入口组件 &#xff08;根组件&#xff0c;所有组件都是从这里开始&#xff…