
C语言程序实现的两种环境:
第一步:翻译环境--使得源程序转换为机器可执行的机器指令
第二步:执行环境--实现可执行代码


多个test.c文件,多个test.obj,生成一个test.exe
编译器介绍:

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

- int main()
- {
- for (int i = 0; i < 10; i++)
- {
- printf("name:%s\tfile:%s \tline:%d \tdate:%s \ttime:%s \ti:%d\n",__func__,__FILE__, __LINE__, __DATE__, __TIME__);
- }
-
- return 0;
- }

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

- #define MAX(x,y) ((x)>(y)?(x):(y))
-
- int main()
- {
- int a = 10;
- int b = 20;
- int c = MAX(a, b);
- printf("%d\n", c);
- return 0;
- }
注意:
- #define定义符号和宏的时候不要带分号
- 参数列表的左括号必须和name紧邻(函数可以,宏不可以)
- 写宏的时候,对于参数不要吝啬括号
- #define NUM 100;//错误用例1
- #define DOUBLE (x) x*x//错误用例2和3
- #define M 100
- #define DOUBLE(x) ((x)+(x))
-
-
- int main()
- {
- int a = DOUBLE(M);
- printf("%d\n", a);
- return 0;
- }
-
- //第一步:-替换M- int a=DOUBLE(100)
- //第二步:-替换X- #define DOUBLE(100) 200
- //第三步:-替换DOUBLE(100)- int a=200;

6-1-1例子1:单纯只是研究辅助打印的信息,没有考虑参数的类型
问:怎么把参数插入到一个字符串中?
- 想法2:函数
- //void Print(int n)
- //{
- // printf("the value of n is &d\n", n);
- //}
-
- //想法3:宏
- //#define PRINT(N) printf("the value of N is %d\n",N)//想法3
-
- //int main()
- //{
- // int a = 10;
- // //printf("the value of a if %d\n", a);
- // Print(a);
- //
- // int b = 20;
- // //:想法1:一个一个打
- // //printf("the value of b is %d\n", b);
- // PRINT(b);
- //
- //
- // return 0;
- //}
-
- //想法4:(最满足用户的做法)#
- #define PRINT(N) printf("the value of "#N" is %d\n",N)
- int main()
- {
- //基石
- printf("hello world\n");
- printf("hello ""world\n");
-
- int a = 10;
- PRINT(a);
- //等价于:printf("the value of ""a"" is %d\n",N);
-
-
- return 0;
- }

6-1-2:考虑到传入的参数的类型 (这使得我想到函数重载)
- #define PRINT(N) printf("the value of "#N" is %d\n",N)
-
- int main()
- {
- int a = 10;
- double pai = 3.14;
- PRINT(a);
- PRINT(pai);
- return 0;
- }
作用:##可以把位于它两边的符号合成一个符号
它允许宏定义从分离的文本片段创建标识符
- #define CAT(name,num) name##num
- int main()
- {
- int song100 = 105;
- printf("%d\n", CAT(song, 100));
- //等价于printf("%d\n",song100)
- return 0;
- }

这里我想解释一下一个东西:
解释:先进行预处理(先合成了classi),再编译
++在宏中的副作用
- #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("%d\n", a);//11
- printf("%d\n", b);//22
- printf("%d\n", c);//21
-
- return 0;
- }
原因:
- 宏的参数是不带计算的替换的(函数的参数是带计算拷贝的)
- 如果宏中有多份++就会执行多次
宏和函数的对比
宏的优点:
- 没有函数调用和函数返回的开销
- 宏的参数与类型无关
宏的缺点:
- 宏是没有办法调试的
- 宏在使用不当,可能会带来运算符优先级和++的副作用问题
- 宏是没办法递归的
应用:stdio.h头文件中好多这种东西,你要看得懂
-
- #define NUM 1
- int main()
- {
- //#if-#else-#endif 分支的条件编译
- #if 0
- printf("hehe\n");
- #else
- printf("haha\n");
- #endif
-
- //#if-#elif-(#else)-#endif 多分支的条件编译
-
- #if NUM==1
- printf("1\n");
- #elif NUM==2
- printf("2\n");
- #else
- printf("0\n");
- #endif
-
- //判断是否#define符号的两种方法
- //方法1:
- #if defined(NUM)
- printf("1\n");
- #endif
-
- //方法2:
- #ifdef NUM
- printf("2\n");
- #endif
-
- //判断是否#undefine符号的两种方法
- //方法1:
- #if !defined(NUM)
- printf("1\n");
- #endif
-
- //方法2:
- #ifndef NUM
- printf("2\n");
- #endif
-
- return 0;
9-1#include<stdio.h>和#inlcude"stdio.h"的区别
查找策略:
#include“include”:先在根目录的的文件中查找,没找到再去目标库里查找
#include<stdio.h>:直接去目标库里查找
所以你的#include<stdio.h>可以写成#include"stdio.h"
但是你的contact.c中不能把#include"conta
ct.h"写成#include<contact.h>

9-2防止头文件被重复包含的两种方法:(写在头文件里的)
多次包含了头文件的危害:平添了几千行代码,使得编译器处理起来压力大
方法1:
- //test.c
- #include<stdio.h>
- #include"stdio.h"
- #include<stdio.h>
-
- //test.h
- #ifndef __TEST_H__
- #define __TEST_H__
-
- #endif
方法2:
- //test.c
- #include<stsdio.h>
- #include<stdio.h>//无效,这一次头文件并没有被包含
-
- #test.h
- #pragma once
