test.c --源文件(源程序)
经过编译生成 ****.exe文件 二进制文件
编译处理的过程 编译器(预编译 编译 汇编)
链接处理的过程 链接
- // 预定义符号
- __FILE__ //进行编译的源文件
- __LINE__ // 文件当前的行号
- __DATE__ // 文件被编译的日期
- __TIME__ // 文件被编译的时间
- __STDC__ // 如果编译器遵循ANSIC,其值为1,否则未定义
- #include
-
- // 预定义符号
- /* __FILE__ //进行编译的源文件
- __LINE__ // 文件当前的行号
- __DATE__ // 文件被编译的日期
- __TIME__ // 文件被编译的时间
- __STDC__ // 如果编译器遵循ANSIC,其值为1,否则未定义
- */
-
- int main()
- {
- printf("%s\n",__FILE__);
- printf("%d\n",__LINE__);
- printf("%s\n",__DATE__);
- printf("%s\n",__TIME__);
- return 0;
- }
运行结果:
把数据写进文件txt中(详细内容看--文件操作这一节内容)
- #include
-
- // 预定义符号
- /* __FILE__ //进行编译的源文件
- __LINE__ // 文件当前的行号
- __DATE__ // 文件被编译的日期
- __TIME__ // 文件被编译的时间
- __STDC__ // 如果编译器遵循ANSIC,其值为1,否则未定义
- */
-
- int main()
- {
- int i = 0;
- int arr[10] ={0};
- FILE *pf = fopen("log.txt","w"); // 打开目标文件
- for (i=0;i<10;i++){
- arr[i]=i;
- fprintf(pf,"file:%s line:%d date:%s time:%s i=%d\n",
- __FILE__ ,__LINE__,__DATE__,__TIME__, i)
- }
- fclose(pf);
- pf = NULL;
- for(i=0;i<10;i++){
- printf("%d",arr[i]);
- }
- return 0;
- }
#define 可以定义标识符,也可以定义宏
- #define MAX 100
- #define reg register //给register重新起个名字叫做reg
- #define do_forever for(;;) //用更形象的符号来替换一种实现
问题:在define定义标识符的时候,要不要在最后加上分号(;)
不要加分号,因为在后面语句中会加分号
#define替换规则
注意:
宏定义的参数是完整的代入表达式 ,宏通常被应用于执行简单的运算(比如比较两个数的大小),宏比函数在程序的规模和速度方面更胜一筹。
宏定义的函数无法被调试
##的作用:可以把位于它两边的符号合成一个符号,它允许宏定义从分离的文本片段创建标识符
属性 | #define定义宏 | 函数 |
---|---|---|
代码长度 | 每次使用时,宏代码都会被插入到程序中,除了非常小的宏之外,程序的长度会大幅度增长 | 函数代码只出现于一个地方,每次使用这个函数,都调用那个地方的同一份代码 |
执行速度 | 更快 | 存在函数的调用和返回的额外开销,所以相对慢一些 |
操作符优先级 | 宏参数的求值是在所有周围表达式的上下文环境里,除非加上括号,否则临近操作符的优先级可能会产生不可预料的后果,所以建议宏在书写的时候多些括号 | 函数参数只在函数调用的时候求值一次,它的结果值传递给函数,表达式的求值结果更容易预测 |
带有副作用的参数 | 参数可能被替换到宏体中的多个位置,所以带有副作用的参数求值可能会产生不可预料的结果 | 函数参数只在传参的时候求值一次,结果更容易控制 |
参数类型 | 宏的参数与类型无关,只要对参数的操作是合法的,它就可以使用于任何参数类型 | 函数的参数是与类型有关的,如果参数的类型不同,就需要不同的函数,即使他们执行的任务是不同的 |
调试 | 不方便调试 | 可以逐语句调试 |
递归 | 不能递归 | 可以递归 |
宏名全部大写,函数名不要全部大写
- #include
// 官方库文件 - #include "****.h" // 自己写的文件
""查找的范围广,但是如果所有的头文件都用“”查找,速度会比较慢
防止头文件被多次重复引用
方法1:传统的写法
- #ifndef __TEST_H__
- #define __TEST_H__
-
- int ADD(int x,int y);
- #endif
方法2:更简洁,现在的写法,不过在老的编译器里会编译不通过,出错
- #pragma once
- int ADD(int x,int y);
用于移除一个宏定义
条件满足,进行编译
用途:调试性的代码,删除可惜,保留又碍事,所以我们可以选择性的编译。
- #include
- #define DEBUG
-
- int main()
- {
- int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
- int i = 0;
- for (i = 0; i < 10; i++)
- {
- arr[i] = 0;
- #ifdef DEBUG
- printf("%d ", arr[i]);
- #endif
- }
- return 0;
- }
常见的条件编译指令
- 1.
- #if 常量表达式
- //
- #endif
- 如:
- #define __DEBUG__ 1
- //
- #endif
-
- 2.多个分支的条件编译
- #if 常量表达式
- //
- #elif 常量表达式
- //
- #elif 常量表达式
- //
- #endif
-
- 3.判断是否被定义
- #if defined(symbol) // 这两条语句等价
- #ifdef symbol
-
- #if !defined(symbol) // 这两条语句等价
- #ifndef symbol