ps.VS→集成开发环境IDE:编辑+编译(编译器cl.exe)+链接(链接器link.exe)+调试
ps.无法解析的外部符号→链接错误
- 程序必须载入内存中。在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。
- 程序的执行便开始。接着便调用main函数(程序的入口)。
- 开始执行程序代码。这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程一直保留他们的值。
- 终止程序。正常or意外终止。
i.e. 已经内定的符号
__FILE__
//进行编译的源文件
__LINE__
//文件当前的行号
__DATE__
//文件被编译的日期
__TIME__
//文件被编译的时间
__STDC__
//如果编译器遵循ANSI C,其值为1,否则未定义
#include
int main()
{
printf("%s\n", __FILE__);
printf("%d\n", __LINE__);
printf("%s\n", __DATE__);
printf("%s\n", __TIME__);
return 0;
}
替换
如果定义的 stuff过长,可以分成几行写,除了最后一行外,每行的后面都加一个反斜杠(续行符)。
本质上是替换所以最好别加 ;
eg
> #define MAX 100;
> int m=MAX;
> 即 int m=100;;
#define name stuff
//name 即 stuff
// 如果定义的 stuff过长,可以分成几行写,除了最后一行外,每行的后面都加一个反斜杠(续行符)。
#define DEBUG_PRINT printf("file:%s\tline:%d\t \
date:%s\ttime:%s\n" ,\
__FILE__,__LINE__ ,\
__DATE__,__TIME__ )
#define MAX 100;
int a = MAX;
//即 int a = 100;
#define name( parament-list ) stuff
注意:
参数列表的左括号必须与name紧邻。如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分。
#define MAX(x,y) (x > y ? x : y)
#define MUL(x,y) x*y
int max(int x, int y)
{
return x * y;
}
int main()
{
int n = MAX(3 + 4, 3 + 1);
int m = max(3 + 2, 4);
int mul = MUL(3 + 2, 4);
printf("n=%d\n", n);
printf("m=%d\n", m);
printf("mul=%d\n", mul);
return 0;
}
- define定义宏使用建议:
- 别乱加空格;
- 牢记替换本质;
- 宏体最好带足括号(整体最好也带括号)(减少操作符优先级而颠倒顺序).
宏体最好带足括号例如
#define MAX(x,y) ((x) > (y) ? (x) : (y))
- 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先被替换。
- 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换。
- 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上述处理过程。
注意:
#define NUM 10
int main()
{
printf("hello NUM");
return 0;
}
#
"hello world"="hello"" world"
//输出的都是:hello world
字符串是有自动连接的特点的
int main()
{
int a = 10;
printf("the value of a is %d\n", a);
float b = 3.1f;
printf("the value of b is %f\n", b);
int c = 13;
printf("the value of c is %d\n", c);
return 0;
}
只有当字符串作为宏参数的时候才可以把字符串放在字符串中。
#define PRINT(val,format) printf("the value of "#val" is "format"\n", val)
int main()
{
int a = 10;
printf("the value of a is %d\n", a);
float b = 3.1f;
printf("the value of b is %f\n", b);
int c = 13;
printf("the value of c is %d\n", c);
PRINT(a, "%d");
PRINT(b, "%f");
PRINT(c, "%d");
return 0;
}
##
##
可以把位于它两边的符号合成一个符号。它允许宏定义从分离的文本片段创建标识符。
注:这样的连接必须产生一个合法的标识符。否则其结果就是未定义的。
副作用就是表达式求值的时候出现的永久性效果。
#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
int main()
{
int x = 5;
int y = 8;
int z = MAX(x++, y++);
printf("x=%d y=%d z=%d\n", x, y, z);
return 0;
}
#define MALLOC(num,type) (type*)malloc(num*sizeof(type))
. (简单的封装)#define MALLOC(num,type) (type*)malloc(num*sizeof(type))
int main()
{
int* p = MALLOC(10, int);
//=(int*)malloc(10*sizeof(int))
return 0;
}
一般来讲函数的宏的使用语法很相似。所以语言本身没法帮我们区分二者。
那我们平时的一个习惯是:把宏名全部大写;函数名不要全部大写
例外:offsetof 、getchar等
这条指令用于移除一个宏定义。
条件编译:满足条件就编译,不满足就不编译
常见的条件编译指令:
1.判断是否被定义
#if defined(symbol) == #ifdef symbol // symbol已被定义则语句被编译
#if !defined(symbol) == #ifndef symbol // symbol未被定义则语句被编译
#include
#define MAX 0
int main()
{
#ifdef MAX
printf("Hello,fantasy_13_7");
#endif // MAX
#undef MAX//取消MAX的定义
#ifdef MAX
printf("Hello,fantasy_13_7");//MAX未定义语句不编译
#endif // MAX
return 0;
}
#if 常量表达式 //...
#endif //常量表达式由预处理器求值。
#define NUM 13
#define A 0
int main()
{
#if 1
printf("Hello,world!\n");
#endif // 1
#if MAX
printf("Hello,Marie!\n");//MAX未定义表达式为假,语句不编译
#endif // MAX
#if 0
printf("Hello,Ada!\n")//0为假,语句不编译
#endif // 0
#if NUM
printf("Hello!\n");
#endif //
#if A
printf("xxxx\n");//A为0表达式为假,语句不编译
#endif // A
return 0;
}
3…多个分支的条件编译(只选择一个分支进入)
#if 常量表达式 //...
#elif 常量表达式 //...
#else //...
#endif
#define NUM 13
#define A 0
int main()
{
#if 1
printf("Hello,world!\n");
#elif MAX
printf("Hello,Marie!\n");
#else
printf("Hello,Ada!\n")
#endif
return 0;
}
4.嵌套指令
#if defined(OS_UNIX)
#ifdef OPTION1 unix_version_option1(); #endif
#ifdef OPTION2 unix_version_option2(); #endif
#elif defined(OS_MSDOS)
#ifdef OPTION2 msdos_version_option2(); #endif
#endif
本地文件#include" "
:先在源文件所在目录下查找,如果该头文件未找到,编译器就像查找库函数头文件一样在标准位置查找头文件。如果找不到就提示编译错误。
库文件#include< >
:查找头文件直接去标准路径下去查找,如果找不到就提示编译错误。
查找策略不一样
ps.库文件也可以用" "
但是查找效率更低
文件中头文件多次被引用,造成了文件内容的重复
#ifndef __TEST_H__
#define __TEST_H__
//头文件的内容
#endif //__TEST_H__
#pragma once
可以避免头文件的重复使用参考《C语言深度解剖》