目录
编译步骤
预处理:gcc -E hello.c -o hello.i
头文件展开
宏替换(其实如果C只是过度阶段之后C++的话宏真的无关紧要)
定义宏:#define 宏名 宏
取消宏:#undef 宏
宏替换作用域为当前文件
条件编译
#if #endif
删除注释
编译:gcc -S hello.i -o hello.s
将预处理后的文件生成汇编文件,进行语法检查
汇编:gcc -c hello.s -o hello.o
将汇编文件编译成二进制文件
链接:gcc hello.o -o hello.exe(hello.out)
将重多二进制文件,库,启动代码生成可以执行文件
宏函数和普通函数
因为宏函数本质是宏替换,所以没有调用过程.有几个宏函数,就替换多少次,造成代码区空间浪费.浪费空间节约时间,以空间换时间.
普通函数在代码区只有一份,调用时读取压栈保存信息,调用结束出栈释放信息(大概是这样函数调用实际上很复杂)这步骤需要时间.以时间换空间.
#include <stdio.h>
//宏函数的本质和宏一样,都是在预编译阶段完成替换
//宏函数不能有类型
//执行 gcc -E xxx.c -o xxx.i 查看.i文件可以查看替换方式
#define ADD(num,num2) (num * num2)
#define ADD2(num,num2) ((num) * (num2))
int main(int argc,char * argv[])
{
//ADD(10, 20) 替换成 (10*20)
printf("ADD(10, 20) = %d\n", ADD(10, 20)); //200
//ADD(10 + 10, 20 + 20) 替换成 (10 + 10 * 20 + 20)
printf("ADD(10 + 10,20 + 20) = %d\n", ADD(10 + 10, 20 + 20)); //230
//ADD2(10 + 10, 20 + 20) 替换成 ((10 + 10)*(20 + 20))
printf("ADD2(10 + 10,20 + 20) = %d\n", ADD2(10 + 10, 20 + 20)); //800
return 0;
}
条件编译
条件编译这块我用linux来说吧.
这个一般调试的时候会用
#include <stdio.h>
int main(int argc,char * argv[])
{
//条件编译 BEBUG就是宏
#ifdef DEBUG
printf("1111111111\n");
#else
printf("222222222\n");
#endif
return 0;
}
-D 是向命令行中传递宏函数,这个之后在Linux中再说
#include <stdio.h>
int main(int argc,char * argv[])
{
//条件编译 BEBUG就是宏
#ifndef DEBUG
printf("1111111111\n");
#else
printf("222222222\n");
#endif
return 0;
}
结果和上面相反
1 #include <stdio.h>
2
3 int main(int argc,char * argv[])
4 {
5 //条件编译 BEBUG就是宏
6 #if 1
7 printf("1111111111\n"); //执行这条语句,如果为0则执行else语句
8 #else
9 printf("222222222\n");
10 #endif
11
12 return 0;
13 }
本来已经要睡着了,被同学一条八卦信息吵醒了,然后想到明天就一个星期了速度是有点慢那就继续吧.
条件编译案例
想不到有啥案例,然后跑到B站看人家的案例,写了一下
#include <stdio.h>
#include <string.h>
int main(int argc,char * argv[])
{
//就是大写转小写,小写转大写
char buf[1024] = "";
//输入字符串
printf("enter string:\n");
//可以获取空格,
fgets(buf, 1024, stdin);
//fgets可以读回车,例如输入aaa 得到的是 'a''a''a''\n''\0'
buf[strlen(buf) - 1] = '\0';
//循环变量
int i = 0;
#ifdef DEBUG
while (buf[i])
{
if (buf[i] <= 'z' && buf[i] >= 'a')
{
buf[i] -= 32;
}
++i;
}
#else
while (buf[i])
{
if (buf[i] <= 'Z' && buf[i] >= 'A')
{
buf[i] += 32;
}
++i;
}
#endif // DEBUG
printf("%s\n", buf);
return 0;
}
防止头文件重复
对了C语言防止头文件重复包含的
#ifndef
#define
#endif
其实就是条件编译,未定义执行时执行,定义是跳过.可以自己把头文件拆开来看看逻辑.即使没明白也没关系(这个也是无关紧要的,用的多了就懂了).
这种防止头文件重复包含时语言本身的特性,考虑到代码移植问题时还是需要使用的.
#pragma noce 也是防止头文件重复包含,它是编译器行为(有可能一些以前的编译器无法识别)