目录
3.2 #if.......#elif.......#else.......#endif条件定义判断
一、 程序的翻译环境和执行环境
C语言的实现存在两个不同的环境
1、翻译环境:源代码被转换为可执行的机器指令
2、执行环境:用于实际执行代码
1.1 翻译环境
每个源文件通过编译过程分别转换成目标代码(object code);每个目标文件由链接器(linker)捆绑在一起,形成一个单一而完整的可执行程序;链接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且它可以搜索程序员个人的程序库,将其需要的函数也链接到程序中。
1.2 编译的几个阶段
1.3 执行环境
程序执行的过程:
1. 程序必须载入内存中。在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。
2. 程序的执行开始,接着便调用main函数。
3. 开始执行程序代码。这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程一直保留他们的值。
4. 终止程序。正常终止main函数;也有可能是意外终止。
二、宏
2.1 宏的申明方式
#define name( parament-list ) stuff。
参数列表的左括号必须与name紧邻。
如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分。宏在定义时尽量不要省略括号,否则会影响运算过程中的优先级。
举例:
#include<stdio.h>
#define DOUBLE(x) ((x)*(x))
int main()
{
int ret = DOUBLE(3 + 1);//ret=((3+1)*(3+1))
printf("%d", ret);
return 0;
}
部分已定义的宏:
__FILE__ :源文件所在的路径地址
__LINE__ :代码当前的行号
__DATE__ :编译的日期
__TIME__ :编译的时间
__STDC__ :如果编译器遵循ANSI C标准,其值为1,否则未定义.visual studio是没有定义__STDC__的
#include<stdio.h>
int main()
{
FILE* pf = fopen("log.txt", "w");//写一个日志文件
if (pf == NULL)
{
perror("fopen");
return 1;
}
int i = 0;
for (i = 0; i < 5; i++)
fprintf(pf, "file:%s,line=%d,date=%s,time=%s,i=%d\n", __FILE__, __LINE__, __DATE__, __TIME__, i);
fclose(pf);
pf = NULL;
return 0;
}
2.2 #和##在宏中的特殊使用
在宏中使用 # ,可以把一个宏参数变成对应的字符串
#include<stdio.h>
#define PRINT(N) printf("the value of "#N" is %d\n",N)//#N相当于“N”,这时参数就变成了字符
int main()
{
int a = 10;
PRINT(a);
int b = 20;
PRINT(b);
return 0;
}
#include<stdio.h>
#define PRINT(N,FORMAT) printf("the value of "#N" is "FORMAT"\n",N)
int main()
{
int a = 10;
int b = 20;
PRINT(a, "%d");//%d的双引号不能丢
PRINT(b, "%d");
return 0;
}
注意FORMAT如果在双引号内,则相当于字符
##可以把位于它两边的符号合成一个符号,起联合作用
#include<stdio.h>
#define CONNET(A,B) A##B
int main()
{
int GOTNUM=100;
printf("%d", CONNET(GOT, NUM));
return 0;
}
2.3 #undef NAME取消宏定义
#undef NAME:这条指令用于移除一个宏定义。
#include<stdio.h>
#define M 10
int main()
{
printf("%d\n", M);
#undef M
printf("%d\n", M);//解除M的定义后,这里M都会报错,提示未定义M
return 0;
}
三、条件编译指令
3.1 #if.......#endif
如果定义条件成立,则执行中间指令;否则不执行。
其中定义可以写成#ifdef/#if defined;未定义可写成#ifndef/#if !defined。举例子:
#include<stdio.h>
#define M
int main()
{
int i = 0;
int arr[5] = { 0 };
for (i = 0; i < 5; i++)
{
arr[i] = i;
//#ifdef M
// printf("%d ", arr[i]);//定义了M,则打印arr[i]
//#endif
#if defined M
printf("%d ", arr[i]);//两种写法均可
#endif
}
return 0;
}
#include<stdio.h>
int main()
{
int i = 0;
int arr[5] = { 0 };
for (i = 0; i < 5; i++)
{
arr[i] = i;
#ifndef M
printf("%d ", arr[i]);//定义了M,则打印arr[i]
#endif
//#if !defined M
// printf("%d ", arr[i]);//两种写法均可
//#endif
}
return 0;
}
3.2 #if.......#elif.......#else.......#endif条件定义判断
#include<stdio.h>
#define M 10
int main()
{
#if M<5
printf("a");
#elif M==5
printf("b");
#else
printf("c");//结果打印C
#endif
return 0;
}
四、头文件被包含的方式
#include "filename"
查找策略:先在源文件所在目录下查找,如果该头文件未找到,编译器就像查找库函数头文件一样在标准位置查找头文件。如果找不到就提示编译错误。
#include <filename.h>
查找策略:查找头文件直接去标准路径下去查找,如果找不到就提示编译错误。
虽然库文件也可以用“ ”包含,但是如果想查找效率高,最好用《》包含。