//源文件 -> 可执行程序
//编译(预编译->编译->汇编)-> 链接
//预编译:1.头文件的包含 #include 预处理指令
// 2.define定义符号的转换 #define
//3.注释删除
//预编译 test.c->test.i 一些文本操作
//编译 test.i->test.s把C语言代码翻译成汇编代码
//汇编 test.s->test.o 把汇编指令翻译成了二进制指令
//
//预处理:相当于根据预处理指令组装新的C / C++程序。经过预处理,会产生一个没有头文件(都已经被展开了)、宏定义(都已经替换了),
// 没有条件编译指令(该屏蔽的都屏蔽掉了),没有特殊符号的输出文件,这个文件的含义同原本的文件无异,只是内容上有所不同。
//
//编译:将预处理完的文件逐一进行一系列词法分析、语法分析、语义分析及优化后,产生相应的汇编代码文件。
// 编译是针对单个文件编译的,只校验本文件的语法是否有问题,不负责寻找实体。
//
//链接:通过链接器将一个个目标文件(或许还会有库文件)链接在一起生成一个完整的可执行程序
//
// 链接程序的主要工作就是将有关的目标文件彼此相连接,也就是将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,
// 使得所有的这些目标文件成为一个能够被操作系统装入执行的统一整体。在此过程中会发现被调用的函数未被定义。需要注意的是,
// 链接阶段只会链接调用了的函数/全局变量,如果存在一个不存在实体的声明(函数声明、全局变量的外部声明),但没有被调用,依然是可以正常编译执行的。
//#define 替换规则
//1.调用宏时,首先对参数进行检查,看是否包含任何由#define定义的符号
// 如果是,则他们首先被替换
//2.替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所覆盖
//3.最后再次对结果文件进行扫描,看看它是否包含任何有#define定义的符号,如果有重复上述动作
// 4.宏参数和#define定义中可以出现其他#define定义的符号。但是对于宏,不能出现递归
// 5.当预处理去搜索#define定义的符号时,字符串常量的内容并不容易被搜索
//
//如何把参数插入到字符串 用#
//#define print(a) printf("the value of "#a" is %d\n",a);
//int main()
//{
// int a = 10;
// print(a);
//
// int b = 20;
// print(b);
// return 0;
//}
//也可以不同数据类型
//#define print(a,format) printf("the value of "#a" is "format"\n",a)
//int main()
//{
// int a = 10;
// double pai = 3.14;
// print(a, "%d");
// print(pai, "%lf");
//
//}
##可以连接两端符号
//#define lj(name,num) name##num
//
//int main()
//{
//
// int class105 = 100;
// printf("%d", lj(class, 105));
//}
//模拟实现atoi
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
enum Status
{
VALUE,//注意逗号
UNVALUE//注意无逗号无分号结尾
}status = UNVALUE;//默认状态为非法状态
int my_atoi(const char* str)
{
assert(str);
//遇到空字符串
if (*str == '\0')
{
return 0;
}
//遇到空格 “ asdd”这种
while (isspace(*str))
{
str++;
}
int flag = 1;
long long n = 0;
//正负号
if (*str == '+')
{
flag = 1;
str++;
}
else if (*str == '-')
{
flag = -1;
str++;
}
//遇到非数字转换停止
while (*str != '\0')
{
if (isdigit(*str))
{
n = n * 10 + flag * (*str - '0');
if (n<INT_MIN || n>INT_MAX)
{
n = 0;
break;
}
}
else
{
break;
}
str++;
}
if (*str == '\0')
{
status = VALUE;
}
return (int)n;
}
int main()
{
char arr[100] = " -55v253";
int ret = my_atoi(arr);
if (status == VALUE)
{
printf("合法转换%d", ret);
}
else
{
printf("非法转换%d", ret);
}
return 0;
}
//条件编译指令包括#if、#ifdef,#ifndef,#else,#elif、#endif
//在大型项目的开发中,这也并不是一个很好的编程习惯,分类放在不同的头文件并根据特点命名是更好的选择,因为这样更加方便代码的管理和维护
//头文件不能定义全局变量,否则如果有多个文件,那链接时会冲突。