栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【程序的编译和预处理】

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【程序的编译和预处理】

 

1.程序的翻译环境&2.执行环境

C语言程序实现的两种环境:

第一步:翻译环境--使得源程序转换为机器可执行的机器指令

第二步:执行环境--实现可执行代码

3.详解:程序的编译和链接(翻译环境)

多个test.c文件,多个test.obj,生成一个test.exe

编译器介绍:

 链接库:库文件里的库函数/第三方库

4.预处理符号详解 4-1内置的预处理符号
int main()
{
	for (int i = 0; i < 10; i++)
	{
		printf("name:%stfile:%s tline:%d tdate:%s ttime:%s ti:%dn",__func__,__FILE__, __LINE__, __DATE__, __TIME__);
	}

	return 0;
}

 5.预处理指令 5-1#define定义符号
#define NUM 100
#define STR "hello world"//字符串也可以使用预处理定义符号

5-2#define定义宏
#define MAX(x,y)  ((x)>(y)?(x):(y))

int main()
{
	int a = 10;
	int b = 20;
	int c = MAX(a, b);
	printf("%dn", c);
	return 0;
}

注意:

  1. #define定义符号和宏的时候不要带分号
  2. 参数列表的左括号必须和name紧邻(函数可以,宏不可以)
  3. 写宏的时候,对于参数不要吝啬括号
#define NUM 100;//错误用例1
#define DOUBLE (x) x*x//错误用例2和3
5-3#define替换规则
#define M 100
#define DOUBLE(x) ((x)+(x))


int main()
{
	int a = DOUBLE(M);
	printf("%dn", a);
	return 0;
}

//第一步:-替换M- int a=DOUBLE(100)
//第二步:-替换X- #define DOUBLE(100) 200
//第三步:-替换DOUBLE(100)- int a=200;

 6。#和##宏的妙用 6-1#

6-1-1例子1:单纯只是研究辅助打印的信息,没有考虑参数的类型

问:怎么把参数插入到一个字符串中?

想法2:函数
//void Print(int n)
//{
//	printf("the value of n is &dn", n);
//}

//想法3:宏
//#define PRINT(N) printf("the value of N is %dn",N)//想法3

//int main()
//{
//	int a = 10;
//	//printf("the value of a if %dn", a);
//    Print(a);
//
//	int b = 20;
//	//:想法1:一个一个打
//	//printf("the value of b is %dn", b);
//	PRINT(b);
//
//
//	return 0;
//}

//想法4:(最满足用户的做法)#
#define PRINT(N) printf("the value of "#N" is %dn",N)
int main()
{
	//基石
	printf("hello worldn");
	printf("hello ""worldn");

	int a = 10;
	PRINT(a);
//等价于:printf("the value of ""a"" is %dn",N);


	return 0;
}

 

6-1-2:考虑到传入的参数的类型 (这使得我想到函数重载)

#define PRINT(N) printf("the value of "#N" is %dn",N)

int main()
{
	int a = 10;
	double pai = 3.14;
	PRINT(a);
	PRINT(pai);
	return 0;
}
 6-2##

作用:##可以把位于它两边的符号合成一个符号

它允许宏定义从分离的文本片段创建标识符

#define CAT(name,num) name##num
int main()
{
	int song100 = 105;
	printf("%dn", CAT(song, 100));
//等价于printf("%dn",song100)
	return 0;
}

 这里我想解释一下一个东西:

解释:先进行预处理(先合成了classi),再编译

6-3带有副作用的宏参数

++在宏中的副作用

#define MAX(m,n) ((m)>(n)?(m):(n))
int main()
{
	//int a = 0;
	//int b = a + 1;
	//b = a++;//带有副作用的语句

	//带有副作用的宏参数
	int a = 10;
	int b = 20;
	int c = MAX(a++, b++);
	//相当于int c=(a++)>(b++)?(a++):(b++);
	//             11    21           22
 
	printf("%dn", a);//11
	printf("%dn", b);//22
	printf("%dn", c);//21
	
	return 0;
}

原因:

  • 宏的参数是不带计算的替换的(函数的参数是带计算拷贝的)
  • 如果宏中有多份++就会执行多次

7.宏和函数的对比(蓝色标明考虑角度)

                                                         宏和函数的对比                                                     

宏的优点:

  1. 没有函数调用和函数返回的开销
  2. 宏的参数与类型无关

宏的缺点:

  1. 宏是没有办法调试的
  2. 宏在使用不当,可能会带来运算符优先级和++的副作用问题
  3. 宏是没办法递归的
8.条件编译

应用:stdio.h头文件中好多这种东西,你要看得懂

#define NUM 1
int main()
{
	//#if-#else-#endif 分支的条件编译
#if 0
	printf("hehen");
#else
	printf("hahan");
#endif

	//#if-#elif-(#else)-#endif 多分支的条件编译

#if NUM==1
	printf("1n");
#elif NUM==2
	printf("2n");
#else
	printf("0n");
#endif

	//判断是否#define符号的两种方法
	//方法1:
#if defined(NUM)
	printf("1n");
#endif

	//方法2:
#ifdef NUM
	printf("2n");
#endif

	//判断是否#undefine符号的两种方法
	//方法1:
#if !defined(NUM)
	printf("1n");
#endif

	//方法2:
#ifndef NUM
		printf("2n");
#endif

		return 0;
9.预处理指令#include

9-1#include和#inlcude"stdio.h"的区别

查找策略:

#include“include”:先在根目录的的文件中查找,没找到再去目标库里查找

#include:直接去目标库里查找

所以你的#include可以写成#include"stdio.h"

但是你的contact.c中不能把#include"conta

ct.h"写成#include

 9-2防止头文件被重复包含的两种方法:(写在头文件里的)

多次包含了头文件的危害:平添了几千行代码,使得编译器处理起来压力大

方法1:

//test.c
#include
#include"stdio.h"
#include

//test.h
#ifndef __TEST_H__
#define __TEST_H__

#endif

方法2: 

//test.c
#include
#include//无效,这一次头文件并没有被包含

#test.h
#pragma once

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/994347.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号