C语言编程入门之程序头文件的简要解析

头文件是扩展名为.h的文件,其中包含C函数的声明和宏定义,也可以多个源文件之间共享。有两种类型的头文件:程序员编写的文件,和编译器中附带的文件。

要求使用头文件的程序,包括通过它,使用C语言预处理指令#include就像所看到的包含stdio.h头文件,它随着编译器自带。

包括一个头文件等于复制头文件的内容,但我们不这样做,因为这很容易出错,一个好主意是我们不复制头文件的内容,特别是包括多个程序的源文件。

在C或C++程序的简单做法是,我们把所有的常量,宏全系统全局变量和函数原型在头文件,其中包括只要它要求包含头文件。

包括/函语法
用户和系统头文件使用预处理指令#include包括在内。它有以下两种形式:

#include <file>

这种形式被用于系统头文件。它会搜索系统目录的标准列表中指定的文件的文件。可以在前面加上目录到这个列表-I选项在编译源代码。

#include "file"

这种形式是用于自己的程序的头文件。它会搜索包含当前文件的目录中的文件命名的文件。可以在前面加上目录到这个列表-I选项在编译源代码。

包括/函操作
#include指令的工作原理是指导C预处理器使用当前的源文件的其余部分,然后再继续扫描指定的文件作为输入。从预处理器的输出包含后跟来自于#include指令后的文本的输出已生成输出,随后从所包含的文件所得的输出。例如,如果有一个头文件 header.h 如下:

char *test (void);

主程序调用使用头文件,类似 program.c 这样:

int x;
#include "header.h"

int main (void)
{
  puts (test ());
}

编译器会看到同样数据流,因为它会如果program.c读取

int x;
char *test (void);

int main (void)
{
  puts (test ());
}

一次性头文件
如果头文件恰好被包含两次,编译器将处理它的内容两次,将导致一个错误。使用标准方法以防止包围文件的全部内容在一个条件,是这样的:

#ifndef HEADER_FILE
#define HEADER_FILE

the entire header file file

#endif

此构建体通常被称为包装#ifndef。当该头被再次包含,条件将是假的,因为HEADER_FILE定义。预处理器将跳过该文件的全部内容,而编译器不会看到它的两次。

计算包函
有时,有必要选择的几个不同的一个头文件被包含到程序中。它们可能会指定的配置参数被用于对不同类型的操作系统,例如。可以用一系列条件句做到这一点,如下所示:

 #if SYSTEM_1
  # include "system_1.h"
#elif SYSTEM_2
  # include "system_2.h"
#elif SYSTEM_3
  ...
#endif

但是,随着它的内容增长就会变得单调乏味,代替预处理器提供了使用宏的头文件名。这就是所谓的计算包括。而不是写一个头文件名#include直接参数,只需把宏的名字代替:

 #define SYSTEM_H "system_1.h"
 ...
 #include SYSTEM_H

SYSTEM_H将被扩展,而预处理器将寻找system_1.h仿佛的#include已经写了原来的方式。 SYSTEM_H可以通过Makefile -D选项定义。

关于头文件重复包含
1、如果头文件A包含头文件C,同时头文件B也包含头文件C,而写的程序中包含了头文件A,头文件B,然后在编译的时候就会出现头文件C重复包含的错误
这个错误 只要在自己写的头文件中这样写

#ifndef X  //X为你的标识符,保持唯一,可以长点,比如 #ifndef _INCLUDE_XXXXXX_H_
#define X

//这里是你的头文件

#endif

上面的X可以随便取名(可以用来“装”头文件,所以X一般取名为大写的头文件的名字,只不过把"."换成“_”),只要保证#ifndef和#define后面是同一个X就可以了,只是一个标识而已。翻译成中文就是,如果已经#define X了,后面的就不执行了。这样在同一个c文件中,保证可以只#include一个头文件,避免“在同一个c文件中对一个头文件include两次”的错误(第一次包含了该头文件后,就已经#define 了一次X,第二次包含时会遇到“#ifndef X”的判断,既然已经定义,只好对这个判断说yes了,后面的不再执行,
头文件就不会再加进去)。

2、写的代码里, 头文件A需要包含头文件B,头文件B需要包含头文件C,这种情况#include A就没有问题,不会出现重复包含的错误

注意:这里的#ifndef预处理是要解决在同一个c文件中包含了两次同一个头文件的错误,而在不同的c文件中是可以包含同一个头文件的。

如果不用#ifndef来对头文件做标记,又想“一劳永逸”地解决问题,不需要担心重复包含,则就要形成自觉,不要在头文件里定义变量或函数,只声明,这样多次include这个头文件时包含的都是声明,就没有问题,因此c语言里是允许多次声明同一个函数或变量的。

(0)

相关推荐

  • C语言在头文件中定义const变量详解

    C语言在头文件中定义const变量详解 在头文件中定义const不会有多变量的警告或错误,如果该头文件被大量包含会造成rom空间的浪费. 通过查看*.i文件的展开呢,可以发现每个.i文件都会有相应的变量展开. 查看*.map文件,能查看到该变量的多个地址分配. 在预编译的时候如果在头文件定义了const变量,每一个包含该头文件的c文件都会将其展开,而在编译的时候不会报错,因为这符合语法规则,每一个包含这个头文件的*.c文件都会编译一次这个变量,分配一个新的地址,然后在链接的时候也不会报错,因为每

  • 浅析C语言头文件和库的一些问题

    使用gcc的编译器 头文件没有包含stdlib.h,使用atoi函数(atoi函数在stdlib.h中才有声明),编译却没有出错 如果编译的时候加上-Wall选项,会有个警告,请问这是为什么?这是因为C语言一个非常傻的规定:一个函数如果没有声明函数原型,其返回值类型就是int(所谓的implicit declaration).由于atoi恰好真返回int,所以你即使不包含它的头文件也不报错.至于这个警告,是为了避免你由于忘记声明函数原型而出错. 编译器对于没有定义过的函数原型直接当作它返回int

  • C语言中常用的几个头文件及库函数

    不完全统计,C语言标准库中的头文件有15个之多,所以我主要介绍常用的这四个头文件stdio.h,string.h,math.h,stdlib.h,以后用到其他的再做补充.下面上干货: 1.<stdio.h>:定义了输入输出函数.类型以及宏,函数几乎占了标准库的1/3. (1)文件访问. FILE *fopen("filename","mode"): 以mode模式打开地址为'filename'的文件,并返回文件指针. 访问模式主要是"r&quo

  • C语言使用stdlib.h库函数的二分查找和快速排序的实现代码

    快速排序: 复制代码 代码如下: #include <stdlib.h>#include <stdio.h>#include <string.h> #define LENGTH(x) sizeof(x)/sizeof(x[0]) /**输出数组元素*\param arr:指向数组的指针*\param len:数组元素的个数*/void print(char (*arr)[10],int len){    int i;    for (i=0;i<len;i++) 

  • C语言编程入门之程序头文件的简要解析

    头文件是扩展名为.h的文件,其中包含C函数的声明和宏定义,也可以多个源文件之间共享.有两种类型的头文件:程序员编写的文件,和编译器中附带的文件. 要求使用头文件的程序,包括通过它,使用C语言预处理指令#include就像所看到的包含stdio.h头文件,它随着编译器自带. 包括一个头文件等于复制头文件的内容,但我们不这样做,因为这很容易出错,一个好主意是我们不复制头文件的内容,特别是包括多个程序的源文件. 在C或C++程序的简单做法是,我们把所有的常量,宏全系统全局变量和函数原型在头文件,其中包

  • 易语言编程入门第一个程序

    目录 易语言的优点: 最早接触易语言是三年前的事情了,那时候是因为DNF这个游戏我才知道了易语言这个编程语言,当时对他就非常的憧憬.只不过那时候易语言的学习资源比较少,而且自身的学业比较重就没有仔细的了解了. 最近几日再回归DNF的时候突然想到了易语言,所以决定抽点空闲时间学习一下,先定一个小目标:做一个DNF的辅助工具!(也许最终都无法完成也说不定) 这是第一天学习的内容 易语言的优点: 1.     代码是中文的,降低了学习的门槛 2.     全可视化编程,即输即画减少了代码出错的可能 3

  • C语言编程入门必背的示例代码整理大全

    目录 一.C语言必背代码前言 二.一部分C语言必背代码 一.C语言必背代码前言 对于c语言来说,要记得东西其实不多,基本就是几个常用语句加一些关键字而已.你所看到的那些几千甚至上万行的代码,都是用这些语句和关键词来重复编写的.只是他们逻辑功能不一样,那如何快速的上手C语言代码,建议多看多写,下面是小编整理的C语言必背代码. 二.一部分C语言必背代码 1.输出9*9成法口诀,共9行9列,i控制行,j控制列. #include "stdio.h" main() {int i,j,resul

  • Go语言编程入门超级指南

    1.序言 Golang作为一门出身名门望族的编程语言新星,像豆瓣的Redis平台Codis.类Evernote的云笔记leanote等. 1.1 为什么要学习 如果有人说X语言比Y语言好,两方的支持者经常会激烈地争吵.如果你是某种语言老手,你就是那门语言的"传道者",下意识地会保护它.无论承认与否,你都已被困在一个隧道里,你看到的完全是局限的.<肖申克的救赎>对此有很好的注脚: [Red] These walls are funny. First you hate 'em,

  • 关于VS2022不能使用<bits/stdc++.h>的解决方案(万能头文件)

    •<bits/stdc++.h>介绍 #include<bits/stdc++.h>包含了目前 C++ 所包含的所有头文件,又称万能头文件,简直是开挂一般的存在. 你编程所需要的头文件基本上都囊括在了该万能头文件中,试想一下,将若干行头文件: #include<iostream> #include<cstdio> #include<string> #include<map> #include<vector> ......

  • linux下socket编程常用头文件(推荐)

    sys/types.h:数据类型定义 sys/socket.h:提供socket函数及数据结构 netinet/in.h:定义数据结构sockaddr_in arpa/inet.h:提供IP地址转换函数 netdb.h:提供设置及获取域名的函数 sys/ioctl.h:提供对I/O控制的函数 sys/poll.h:提供socket等待测试机制的函数 其他在网络程序中常见的头文件 unistd.h:提供通用的文件.目录.程序及进程操作的函数 errno.h:提供错误号errno的定义,用于错误处理

  • C语言头文件<string.h>函数详解

    目录 1. strlen —— 求字符串长度 1.1 strlen 的声明与用处 1.2 strlen 的用法 1.3 strlen 的模拟实现 2. strcpy —— 字符串拷贝 2.1 strcpy 的声明与用处 2.2 strcpy 的用法 2.3 strcpy 的模拟实现 3. strcmp —— 字符串比较 3.1 strcmp 的声明与用处 3.2 strcmp 的用法 3.3 strcmp 的模拟实现 4. strcat —— 字符串追加 4.1 strcat 的声明与用处 4.

  • C语言编程中从密码文件获取数据的函数总结

    C语言getpw()函数:取得指定用户的密码文件数据 头文件: #include <pwd.h> #include <sys/types.h> 定义函数: int getpw(uid_t uid, char *buf); 函数说明:getpw()会从/etc/passwd中查找符合参数uid所指定的用户账号数据, 找不到相关数据就返回-1. 所返回的buf 字符串格式如下: 账号:密码:用户识别码(uid):组识别码(gid):全名:根目录:shell 返回值:返回 0 表示成功,

随机推荐