2024年C C++最全【C语言】预处理详解_c语言静态内存defin(2),2024年最新面试官6个灵魂拷问

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

2️⃣ 宏替换
3️⃣ 去注释
test.c -> test.i

编译:

1️⃣ 把C语言代码转化为汇编代码
2️⃣ 进行了 语法分析,词法分析,语义分析,符号汇总(全局符号例如main函数、函数名)
test.i -> test.s

汇编:

1️⃣把汇编代码转换成二进制指令
2️⃣ 形成符号表(函数名加上地址)
test.s -> test.o

链接:

1️⃣ 合并段表(把相同的内容合并到一个区域)
2️⃣ 符号表的合并和重定位(声明处的地址没有意义,合并选择有意义的)
test.o -> text.exe


1.3 运行环境

程序执行的过程:

1)程序必须载入内存中。在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。
2)程序的执行便开始。接着便调用main函数。
3)开始执行程序代码。这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程一直保留他们的值。
4)终止程序。正常终止main函数;也有可能是意外终止。


二、详解预处理

2.1 预定义符号

C语言提供了一些能直接被使用的符号:

\_\_FILE\_\_  //进行编译的源文件
\_\_LINE\_\_  //文件当前的行号
\_\_DATE\_\_  //文件被编译的日期
\_\_TIME\_\_  //文件被编译的时间
__STDC__  //如果编译器遵循ANSI C,其值为1,否则未定义

int main()
{
	FILE\* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		return EXIT_FAILURE;
	}
	for (int i = 0; i < 5; i++)
	{
		fprintf(pf, "file:%s line:%d date:%s time:%s\n", \_\_FILE\_\_, \_\_LINE\_\_, \_\_DATE\_\_, \_\_TIME\_\_);
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

在这里插入图片描述


2.2 #define

语法:

#define name stuff

#define MAX 100
#define STR "abc"

int main()
{
	printf("%d %s", MAX, STR);
	return 0;
}

预处理后:

int main()
{
	printf("%d %s", 100, "abc");
	return 0;
}

#define的后面不要加 ;
续航符:

#define DEBUG\_PRINT printf("file:%s\tline:%d\t \
 date:%s\ttime:%s\n" ,\
 \_\_FILE\_\_,\_\_LINE\_\_ , \
 \_\_DATE\_\_,\_\_TIME\_\_ )


2.3.1 #define定义宏
#define name( parament-list ) stuff

比如现在实现一个平方的宏:

#define SQUARE( x ) ((x) \* (x))

int main()
{
	printf("%d", SQUARE(5));
	return 0;
}

因为宏是直接替换代码,所以有些情况下会有符号优先级问题,所以应该尽量多加一些括号。


2.3.2 #define 替换规则

在程序中扩展#define定义符号和宏时,需要涉及几个步骤。

  1. 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先
    被替换。
  2. 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换。
  3. 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上
    述处理过程。

注意

  1. 宏参数和#define 定义中可以出现其他#define定义的符号。但是对于宏,不能出现递归。
  2. 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。

2.3.3 #和##

#:
把参数写进字符串

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

int main()
{
	int n = 10;
	PRINT(n);
	return 0;
}

在这里插入图片描述
#n会转化成"n"。


##:
合并符号

#define CAT(a, b) a##b

int main()
{
	printf("%s\n", CAT("abc", "def"));
	int ABC = 1;
	printf("%d\n", CAT(A, BC));
	return 0;
}

在这里插入图片描述

2.3.4 带副作用的宏
#define MAX(a, b) (a) > (b) ? (a) : (b)

int main()
{
	int a = 5;
	int b = 4;
	int m = MAX(a++, b++);
	printf("%d\n", m);
	printf("%d %d", a, b);
	return 0;
}

结果:

6
7 5

本意是求较大值,这种重复计算就是副作用。


2.3.5 宏和函数

比较大小的宏和函数:

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

int Max(int a, int b)
{
	return (a > b ? a : b);
}

宏的优点:

1️⃣ 函数必须声明类型,而宏不用,宏是类型无关的
2️⃣ 宏的效率要高于函数,因为函数需要创建栈帧和参数传参等。

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

必须声明类型,而宏不用,宏是类型无关的

2️⃣ 宏的效率要高于函数,因为函数需要创建栈帧和参数传参等。

[外链图片转存中…(img-w8WYsxBR-1715533906489)]
[外链图片转存中…(img-F56xC31g-1715533906489)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值