C语⾔头⽂件到底是什么?
⼀,.h头⽂件会参与编译吗?
不妨来做个实验
这个是head.h⽂件的内容
#include <stdio.h>
int main() {
printf(“Hello World!”);
return 0;
}
这个是ori.c⽂件的内容
#include “head.h”
编译执⾏gcc ori.c -o ori
发现输出的是
.\
hello world!
.c⽂件中并没有引⼊任何其他的⽂件,除了我们⾃⼰定义的head.h头⽂件,⽽在这个头⽂件中,我们引⼊了stdio.h头⽂件,并且我们在head.h⾥⾯定义的main函数被执⾏了,由此证明了include xxx.h是直接原封不同的插⼊到引⽤这个头⽂件的.c⽂件中的。
但是会参与编译吗?
为此设计下⾯这个实验:
开⼀个项⽬,在.h头⽂件⾥⾯定义main函数,
不引⽤这个头⽂件直接编译整个项⽬,然后执⾏,
如果没有输出main函数内部的内容,那么表明如果不加引⽤,.h⽂件不参与编译。
否则就参与编译。
这个是head.h⽂件内容
#include <stdio.h>
int main() {
printf(“Hello World! I am head.h”);
return 0;
}
这个是ori.c⽂件的内容
// nothing
编译执⾏gcc ori.c -o ori
发现输出的是
C:/Program Files/MinGW/bin/…/lib/gcc/x86_64-w64-mingw32/8.1.0/…/…/…/…/x86_64-w64-mingw32/lib/
…/lib/libmingw32.a(lib64
_libmingw32_a-crt0_c.o):crt0_c.c:(.text.startup+0x2e): undefined reference to `WinMain’
<: error: ld returned 1 exit status
报错了,undefined reference to WinMain未定义WinMain
这时候我们在ori.c内部定义这样的⼀个函数
#include <stdio.h>
int WinMain() {
printf(“Hello world! I am WinMain!”);
return 0;
}
再次编译运⾏gcc ori.c -o ori
运⾏.\
.\
Hello world! I am WinMain!
发现正常输出了WinMain函数内部的内容,这也告诉我们WinMain函数同样可以作为程序的⼊⼝。
经过实验发现,的的确确.h绝对不是直接参与编译的,⽽是通过.c⽂件中#include "xxx.h"语句⼿动插⼊的。
这其实间接解答了在.h头⽂件中定义的静态局部变量⽆法局部化的原因。
⼆, .h头⽂件中的静态全局变量为什么可以被访问?
我们在学习C语⾔初期就直到,如果对⼀个全局变量使⽤static语句修饰的话,就可以把这个变量限制在本⽂件的访问域内,⽽⽆法被其他⽂件访问,但是这⼀点对于.h⽂件中⽆效,该访问还是可以访问?下⾯看⼀下实验
创建三个⽂件ori1.c, ori2.c, head.h
在ori1.c中写下以下内容
#include <stdio.h>
extern int A;
extern int B;
system的头文件int main() {
printf(“A = %d\n”, A);
printf(“B = %d”, B);
return 0;
}
在ori2.c中写下以下内容
#include <stdio.h>
int A = 12;
static B = 13;
此时在head.h中不写⼊任何内容
编译运⾏
正如和我们学过的⼀样,出现了未定义的错误
undefined reference to `B’
<: error: ld returned 1 exit status
静态全局变量不可以被其他变量修改
这时候我们给ori2.h添加两个函数
void getB() {
printf(“B = %d\n”, B);
}
void changeB(int num) {
B = num;
}
然后在ori1.c中去声明应⽤⼀下这两个函数
#include <stdio.h>
extern int A;
extern void getB();
extern void changeB(int B);
int main() {
printf(“A = %d\n”, A);
getB();
changeB(1600);
getB();
return 0;
}
编译运⾏
A = 12
B = 13
B = 1600
虽然⽆法直接访问,但是可以定义ori2.c⽂件⾥⾯的函数去对该变量访问,这或许就是私有变量的雏形吧!
下⾯再来看看有关于.h中的全局变量,
由于我们已经知道了是完全插⼊的形式,那么我们可以理解到这个定义的静态全局变量是定义在引⽤它的⽂件⾥⾯
根据前⽂中定义在⾃⼰⽂件内部的静态全局变量只能被⾃⼰访问,那么结果⾃然显⽽易见了,
.h⽂件中的静态全局变量作⽤域是引⽤这个头⽂件的.c⽂件
⾃然⽽然的,我们应当明⽩,如果⼀个.h⽂件中定义过多的全局变量,那么这个全局变量被其他的变量引⽤的时候就会出现访问⽆指向的错误!重复定义
建议尽可能少在.h头⽂件中定义全局变量,或者静态全局变量
三,条件编译
C语⾔编译是把整个项⽬编译,⽽很多的.c⽂件都需要引⽤同⼀个函数,⽽正对于不同的系统⼜出现了不同的编译模式,如果说要把所有的.c⽂件头部都写⼊那些描述条件编译的代码,那么所有的代码写起来会复杂⽆⽐
所以把条件编译代码放在.h⽂件⾥⾯,直接配置好才是⼀个好的选择。
条件编译的例⼦
#include <stdio.h>
#include <stdlib.h>
int main() {
#if _WIN64
system(“color 0c”);
printf(“Hello World!”);
#elif linux
printf("\033[22;31mHello World!\n\033[22;30m\");
#else
printf(“Hello World!”);
#endif
return 0;
}
#include <stdio.h>
int main() {
#if _WIN64
printf(“This is Windows!\n”);
#else
printf(“Unknown platform!\n”);
#endif
#if linux
printf(“This is Linux!\n”);
#endif
return 0;
}
使⽤#ifdef判断宏是否被编译过,与之对应的还有⼀个#ifndef表⽰如果没有被定义的话、
#include <stdio.h>
#include <stdlib.h>
int main(){
#ifdef _DEBUG
printf(“正在使⽤ Debug 模式编译程序…\n”);
#else
printf(“正在使⽤ Release 模式编译程序…\n”);
#endif
system(“pause”);
return 0;
}
#if后⾯接的是整形常量表达式,⽽#ifdef后⾯只能接宏名
⼜由于⾃⼰可以定义宏,⾃然⽽然的⾃⼰就可以配置出⾃⼰的项⽬的条件编译。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。