extern与头文件(h)的区别和联系
.c和.h文件的区别
.c和.h文件的区别一个简单的问题:.c和.h文件的区别学了几个月的C语言,反而觉得越来越不懂了。
同样是子程序,可以定义在.c文件中,也可以定义在.h文件中,那这两个文件到底在用法上有什么区别呢?2楼:子程序不要定义在.h中。
函数定义要放在.c中,而.h只做声明.否则多引用几次,就会发生函数重复定义的错误。
3楼:.h只做声明,编译后不产生代码4楼:这样做目的是为了实现软件的模块化使软件结构清晰,而且也便于别人使用你写的程序纯粹用 C 语言语法的角度,你当然可以在 .h 中放任何东西,因为#include 完全等价于把 .h 文件 Ctrl-C Ctrl-V 到 .c 中.h 中应该都是一些宏定义和变量、函数声明,告诉别人你的程序“能干什么、该怎么用”.c 中是所有变量和函数的定义,告诉计算机你的程序“该怎么实现”5楼:当然,如果一个 .h 被多个 .c 包含而且 .h 中有对象(变量或函数)的定义,就会发生重复定义的错误了声明可以无穷多次,定义只能一次6楼:一般来说,一个C文件应该是一个模块如果你的程序仅仅有一个模块(仅仅一个C文件),就可以不用建立H文件了。
否则你的模块肯定不是独立的,你的模块里面的实现要被别的模块调用。
这个时候你最好生成一个头文件(H文件),在头文件里面可以声明你的那些函数是公共的。
当别的模块包含你的头文件后,就可以使用你的公共声明了。
7楼:一个C对应一个H,这样管理起来方便比如你有一个"feed_dog.c",那么就再添加一个"feed_dog.h":#ifndef _feed_dog_h#define _feed_dog_hextern void feed_dog(void);#endif其实在H文件里写函数也无所谓,只是不符合习惯而已。
只要按照以上的格式写,一个H文件添加多少次都无所谓,呵呵8楼:只是一种约定在编译器里面,.c和.h是没有区别的,.c和.h如何使用完全取决于程序员,不过为了你的程序以后还能看懂而且别人也能看懂,请遵守普遍的约定,这些约定前面的大虾们已经讲了很多了.这个就象汽车在马路上要靠右行使一样,是人为约定,汽车(编译器)本身并不知道自己是在靠左还是靠右行使.如果你喜欢,还可以用任意后缀命名源文件和头文件,但这样干可能会导致集成编译和调试环境罢工,你只好自己写makefile文件了.9楼:非常感谢各位大侠,不过我现在越来越糊涂了1,当一个函数要经常使用(比如有十几个C文件使用它)时,一般我都放在H文件里,并在前面加上__inline.对于__inline函数,很多C文件都可以INCLUDE这个H文件,但是它好象只能被一个H文件INCLUDE,如果有两个H文件INCLUDE它,就会出现编译错误。
c语言中.c文件与.h文件的关联
c语言中.c文件与.h文件的关联
一般一个C文件要搭配一个H文件,两者文件名相同,如 UART.c 对于UART.h ,其它函数通过#include"UART.h",来调用UART.c里面定义的函数和变量
H文件里面是对同名的C文件里面内容的声明,C文件必须include同名的头文件,一般C文件需要用到的其它头文件(比如stdio.h),也在H文件里包含,见下面的例子
头文件一般要写成条件包含,这样在重复包含时,编译器自动把已经包含过的文件忽略掉
#ifndef __XXX_H
#define__XXX_H
#include
.....
#endif
C文件里面写好的函数,要在对于的H文件挂个名,叫其它包含这个H的C文件知道这个函数的存在
H文件就像一个销售部,C文件是生产部,客户了解一个公司的产品都是从销售部了解的,不会关注他是怎么生产的;另一方面,销售部挂的东西,都是根据生产部来的,两个文件的关系基本可以用这个来比喻
C文件里面定义的全局变量要在头文件里面加extern 声明,叫其它包含这个H的C文件知道这里还有个全局变量
H文件里面可以定义宏,什么是宏?看--> #define LEDBLINK() PORTA ^= (1<< LED) C文件直接使用LEDBLINK(); 编译之前会用PORTA ^= (1<< LED) 来进行替换
其它结构体也是要在H里面定义类型,但是必须在C文件里面例化。
C语言中变量的声明和定义
C语⾔中变量的声明和定义变量声明和变量定义变量定义:⽤于为变量分配存储空间,还可为变量指定初始值。
程序中,变量有且仅有⼀个定义。
变量声明:⽤于向程序表明变量的类型和名字。
定义也是声明,extern声明不是定义定义也是声明:当定义变量时我们声明了它的类型和名字。
extern声明不是定义:通过使⽤extern关键字声明变量名⽽不定义它。
[注意]变量在使⽤前就要被定义或者声明。
在⼀个程序中,变量只能定义⼀次,却可以声明多次。
定义分配存储空间,⽽声明不会。
C++程序通常由许多⽂件组成,为了让多个⽂件访问相同的变量,C++区分了声明和定义。
变量的定义(definition)⽤于为变量分配存储空间,还可以为变量指定初始值。
在程序中,变量有且仅有⼀个定义。
声明(declaration)⽤于向程序表明变量的类型和名字。
定义也是声明:当定义变量的时候我们声明了它的类型和名字。
可以通过使⽤extern声明变量名⽽不定义它。
不定义变量的声明包括对象名、对象类型和对象类型前的关键字extern。
extern声明不是定义,也不分配存储空间。
事实上它只是说明变量定义在程序的其他地⽅。
程序中变量可以声明多次,但只能定义⼀次。
只有当声明也是定义时,声明才可以有初始化式,因为只有定义才分配存储空间。
初始化式必须要有存储空间来进⾏初始化。
如果声明有初始化式,那么它可被当作是定义,即使声明标记为extern。
任何在多⽂件中使⽤的变量都需要有与定义分离的声明。
在这种情况下,⼀个⽂件含有变量的定义,使⽤该变量的其他⽂件则包含该变量的声明(⽽不是定义)。
如何清晰的区分变量声明和定义extern通知编译器变量在其他地⽅被定义1.extern告诉编译器变量在其他地⽅定义了。
例如:extern int i;//声明,不是定义int i;//声明,也是定义,未初始化带有初始化式的声明必定式定义2.如果声明有初始化式,就被当作定义,即使前⾯加了extern。
c语言.h文件例子
c语言.h文件例子C语言中的.h文件通常是头文件,用于声明函数、变量和常量等。
它们通常包含在C源代码文件中,以便在多个文件中共享这些声明。
下面我将从不同角度给出关于C语言.h文件的例子。
1. 函数声明:一个.h文件中可以包含函数的声明。
例如,一个名为math.h的头文件可以包含数学函数的声明,如下所示:c.// math.h.#ifndef MATH_H.#define MATH_H.int add(int a, int b);float divide(float a, float b);#endif.这里,我们使用了#ifndef、#define和#endif来防止头文件被多次包含。
2. 变量声明:头文件还可以包含变量的声明。
例如,一个名为constants.h的头文件可以包含常量的声明,如下所示:c.// constants.h.#ifndef CONSTANTS_H.#define CONSTANTS_H.#define PI 3.14159。
extern int globalVar;#endif.这里,我们使用了#define来定义常量,使用extern关键字来声明全局变量,但不进行定义。
3. 结构体和类型声明:头文件还可以包含结构体和自定义类型的声明。
例如,一个名为structs.h的头文件可以包含结构体和类型的声明,如下所示:c.// structs.h.#ifndef STRUCTS_H.#define STRUCTS_H.typedef struct {。
int x;int y;} Point;typedef enum {。
RED,。
GREEN,。
BLUE.} Color;#endif.这里,我们使用了typedef关键字来定义新的数据类型。
4. 宏定义:头文件还可以包含宏定义,用于简化代码中的重复操作。
例如,一个名为macros.h的头文件可以包含宏定义,如下所示:c.// macros.h.#ifndef MACROS_H.#define MACROS_H.#define MAX(x, y) ((x) > (y) ? (x) : (y))。
解析extern
//B.CPP
void func()
{
}
程序的结构是这样的:在文件B.CPP中定义了一个函数void func(),main函数位于文件A.CPP,在main函数中调用了B中定义的函数func()。
要在A中调用B中定义的函数,必须要加上该函数的声明。
如本例中的void func();就是对函数func()的声明。
如果没有声明的话,编译A.CPP时就会出错。
因为编译器的目光只局限于被编译文件,必须通过加入函数声明来告诉编译器:“某个函数是定义在其它的文件中的,你要放行!”,这一点跟用extern来声明外部全局变量是一个道理。
需要注意的是,一般的程序都是通过包含头文件来完成函数的声明。
拿本例来说,一般是创建一个头文件B.H,在头文件中加入声明语句void func(); 并且在A.CPP中加入包含语句:#include “B.H”。
在C++程序中,头文件的功能从函数声明被扩展为类的定义。
不同编译方式下的函数调用
如果在工程中,不仅有CPP文件,还有以C方式编译的C文件,函数调用就会有一些微妙之处。
我们将B.CPP改作B.C:。
C语言的变量作用域及头文件
C语言的变量作用域及头文件C语言是一种结构化的、过程型的通用编程语言,广泛用于系统编程和应用编程。
在C语言中,变量作用域指的是变量在程序中的可见范围,而头文件则是用来引入其他源文件中定义的函数和变量的文件。
一、变量作用域1.全局作用域在C语言中,全局变量在定义它的源文件中全局可见,也可以通过extern关键字在其他源文件中访问。
全局变量的生命周期与整个程序的运行周期相同。
全局变量在任何地方都可以使用,但应注意避免滥用全局变量,以避免潜在的命名冲突和程序难以维护的问题。
2.局部作用域局部变量只在其定义的函数、语句块或者循环等局部范围内可见,超出这个范围后就无法访问。
局部变量的生命周期仅限于其所在的函数、语句块或是循环等。
局部变量的作用是封装数据,提高程序的模块性和可读性,避免命名冲突,并可以节省内存空间。
3.形式参数作用域形式参数是函数定义中指定的参数,参数列表位于函数的括号中。
形式参数只在函数内部可见,在函数调用时将实际参数传递给形式参数,从而进行函数的运算。
形式参数的作用是接收传入的实际参数,供函数内部使用。
参数的命名应该具有描述性,以增加程序的可读性。
二、头文件C语言中的头文件使用扩展名为.h,用于定义函数原型、数据类型、宏定义等信息,并提供给其他源文件进行引用。
头文件的作用是将相关的代码集中到一个文件中,方便代码的维护和重用。
常用的头文件有stdio.h、stdlib.h、string.h等,它们包含了许多C语言的标准函数和宏定义。
使用头文件的方式是使用#include指令将头文件包含到源文件中。
头文件的编写应尽量使用头文件宏和条件编译等技术,避免多次包含同一个头文件以及头文件之间的依赖关系。
在编写自己的头文件时,需要注意以下几点:1.避免在头文件中定义全局变量,以免造成重复定义错误或者命名冲突。
2. 使用#ifndef、#define、#endif等预处理指令来防止头文件的重复包含。
3.在头文件中只定义函数原型、数据类型和宏定义等,不要在头文件中实现函数的具体代码,以免造成重复定义错误。
C语言模块化编程
当你在一个项目小组做一个相对较复杂的工程时,意味着你不再独自单干。
你需要和你的小组成员分工合作,一起完成项目,这就要求小组成员各自负责一部分工程。
比如你可能只是负责通讯或者显示这一块。
这个时候,你就应该将自己的这一块程序写成一个模块,单独调试,留出接口供其它模块调用。
最后,小组成员都将自己负责的模块写完并调试无误后,由项目组长进行组合调试。
像这些场合就要求程序必须模块化。
模块化的好处是很多的,不仅仅是便于分工,它还有助于程序的调试,有利于程序结构的划分,还能增加程序的可读性和可移植性。
初学者往往搞不懂如何模块化编程,其实它是简单易学,而且又是组织良好程序结构行之有效的方法之一.本文将先大概讲一下模块化的方法和注意事项,最后将以初学者使用最广的keil c 编译器为例,给出模块化编程的详细步骤。
模块化程序设计应该理解以下概述:(1)模块即是一个.c 文件和一个.h 文件的结合,头文件(.h)中是对于该模块接口的声明;这一条概括了模块化的实现方法和实质:将一个功能模块的代码单独编写成一个.c 文件,然后把该模块的接口函数放在.h文件中.举例:假如你用到液晶显示,那么你可能会写一个液晶驱动模块,以实现字符、汉字和图像的现实,命名为: led_device. c,该模块的.c文件大体可以写成:/************************************************* ************************* 液晶驱动模块** 文件: lcd_device.c* 编写人: 小瓶盖* 描述:液晶串行显示驱动模块,提供字符、汉字、和图像的实现接口* 编写时间: 2009.07.03* 版本:1.2************************************************** ***********************/#include ……//定义变量unsigned char flag;//局部变量static unsigned char value;//全局变量…//定义函数//这是本模块第一个函数,起到延时作用,只供本模块的函数调用,所以用到static 关键字修饰/********************延时子程序********************** **/static void delay (uint us) //delay time{}//这是本模块的第二个函数,要在其他模块中调用/*********************写字符程序********************* ******* 功能:向LCD写入字符** 参数:dat_comm 为1写入的是数据,为0写入的是指令content 为写入的数字或指令************************************************** ****/void wr_lcd (uchar dat_comm,uchar content){}…………/***************************** END Files************ ***********************/注:此处只写出这两个函数,第一个延时函数的作用范围是模块内,第二个,它是其它模块需要的。
extern变量的用法
extern变量的用法extern关键字是C语言中常用的一个关键字,用于声明一个全局变量。
与普通的全局变量不同的是,extern关键字用来告诉编译器该变量是在其他文件中定义的,是一个外部变量。
在C 语言中,extern变量的引用和定义都要考虑到其作用域和生存周期的问题。
在C语言中,头文件(.h文件)中常用extern来声明外部变量,然后在源文件(.c文件)中定义这个全局变量。
在其他需要使用该全局变量的源文件中,再通过#include指令包含这个声明的头文件。
extern的作用主要有三个方面:解决多文件共享问题、避免重复定义和提高可维护性。
1. 解决多文件共享问题在C语言中,一个程序通常会由多个源文件组成,每个源文件可以有自己的全局变量。
如果不使用extern,每个源文件都会拥有一个独立的全局变量副本,无法实现数据的共享。
通过使用extern关键字,就可以声明并引用其他源文件中定义的全局变量,实现数据的共享。
例如,我们有两个文件file1.c和file2.c,需要共享一个全局变量count:file1.c:```c#include <stdio.h>extern int count; // 声明外部全局变量void increase();int main() {printf("File 1: count = %d\n", count);increase();printf("File 1: count = %d\n", count);return 0;}```file2.c:```cint count = 10; // 全局变量的定义void increase() {extern int count; // 声明外部全局变量count++;}```上述代码中,file1.c通过extern关键字声明了一个外部全局变量count,然后在main函数中引用了这个变量。
.c和.h文件的区别
.c和.h文件的区别一个简单的问题:.c和.h文件的区别学了几个月的C语言,反而觉得越来越不懂了。
同样是子程序,可以定义在.c文件中,也可以定义在.h文件中,那这两个文件到底在用法上有什么区别呢?2楼:子程序不要定义在.h中。
函数定义要放在.c中,而.h只做声明.否则多引用几次,就会发生函数重复定义的错误。
3楼:.h只做声明,编译后不产生代码4楼:这样做目的是为了实现软件的模块化使软件结构清晰,而且也便于别人使用你写的程序纯粹用 C 语言语法的角度,你当然可以在.h 中放任何东西,因为#include 完全等价于把.h 文件Ctrl-C Ctrl-V 到.c 中.h 中应该都是一些宏定义和变量、函数声明,告诉别人你的程序“能干什么、该怎么用”.c 中是所有变量和函数的定义,告诉计算机你的程序“该怎么实现”5楼:当然,如果一个.h 被多个.c 包含而且.h 中有对象(变量或函数)的定义,就会发生重复定义的错误了声明可以无穷多次,定义只能一次6楼:一般来说,一个C文件应该是一个模块如果你的程序仅仅有一个模块(仅仅一个C文件),就可以不用建立H文件了。
否则你的模块肯定不是独立的,你的模块里面的实现要被别的模块调用。
这个时候你最好生成一个头文件(H文件),在头文件里面可以声明你的那些函数是公共的。
当别的模块包含你的头文件后,就可以使用你的公共声明了。
7楼:一个C对应一个H,这样管理起来方便比如你有一个"feed_dog.c",那么就再添加一个"feed_dog.h":#ifndef _feed_dog_h#define _feed_dog_hextern void feed_dog(void);#endif其实在H文件里写函数也无所谓,只是不符合习惯而已。
只要按照以上的格式写,一个H文件添加多少次都无所谓,呵呵8楼:只是一种约定在编译器里面,.c和.h是没有区别的,.c和.h如何使用完全取决于程序员,不过为了你的程序以后还能看懂而且别人也能看懂,请遵守普遍的约定,这些约定前面的大虾们已经讲了很多了.这个就象汽车在马路上要靠右行使一样,是人为约定,汽车(编译器)本身并不知道自己是在靠左还是靠右行使.如果你喜欢,还可以用任意后缀命名源文件和头文件,但这样干可能会导致集成编译和调试环境罢工,你只好自己写makefile文件了.9楼:非常感谢各位大侠,不过我现在越来越糊涂了1,当一个函数要经常使用(比如有十几个C文件使用它)时,一般我都放在H文件里,并在前面加上__inline.对于__inline 函数,很多C文件都可以INCLUDE这个H文件,但是它好象只能被一个H文件INCLUDE,如果有两个H文件INCLUDE它,就会出现编译错误。
extern 的用法
extern 的用法extern是C/C++语言中的关键字,用于告知编译器某个变量、函数或对象的定义存在于其他文件中。
使用extern关键字,可以在当前文件中引用其他文件中定义的变量、函数、对象等。
具体用法如下:1.在当前文件中声明变量的外部引用:当在一个C/C++文件中需要使用其他文件定义的全局变量时,可以使用extern关键字来声明该变量的外部引用。
例如:```c++extern int global_variable; //声明全局变量global_variable 的外部引用```2.在当前文件中声明函数的外部引用:当在一个C/C++文件中需要调用其他文件中定义的函数时,可以使用extern关键字来声明该函数的外部引用。
例如:```c++extern void external_function(); //声明函数external_function的外部引用```3.在头文件中声明共享的全局变量和函数:当多个源文件需要共享同一个全局变量或函数时,可以将其定义在一个头文件中,并在其他源文件中使用extern关键字来声明外部引用。
例如,在header.h 文件中定义了一个全局变量和函数:```c++// header.hextern int shared_variable; //全局变量shared_variable的定义extern void shared_function(); //函数shared_function的定义```然后在其他源文件中使用该头文件并声明外部引用:```c++// main.c#include "header.h"int main() {shared_variable = 10; //使用共享的全局变量shared_function(); //调用共享的函数return 0;}```除了以上用法,还可以进一步拓展extern关键字的用途:-在C++中用于在类的声明中指示函数的定义位于类的外部。
h文件作用
C语言的著作中,至今还没发现把.h文件的用法写的透彻的。
在实际应用中也只能依葫芦画瓢,只知其然不知其所以然,甚是郁闷!闲来无事,便将搜集网络的相关内容整理一下,以便加深自己的理解理论概述:.h中一般放的是同名.c文件中定义的变量、数组、函数的声明,需要让.c外部使用的声明。
1)h文件作用:1.方便开发:包含一些文件需要的共同的常量,结构,类型定义,函数,变量申明;2. 使函数的作用域从函数声明的位置开始,而不是函数定义的位置(实践总结)3 .提供接口:对一个软件包来说可以提供一个给外界的接口(例如: stdio.h)。
2)h文件里应该有什么:常量,结构,类型定义,函数,变量申明。
3)h文件不应该有什么:变量定义, 函数定义。
4)extern问题:1.对于变量需要extern;2.对于函数不需要因为函数的缺省状态是extern的.如果一个函数要改变为只在文件内可见,加static。
5)include包含问题:虽然申明和类型定义可以重复,不过推荐使用条件编译。
#ifndef _FILENAME_H,#define _FILENAME_H……#endif实践总结:先看最简单的程序:hello world1/*test1.c*/2 main()3 {4printf("Hello World!\n");5 }注意,test1中并没有.h文件,编译可以顺利通过。
把程序做下改动,下面这个:1/*test2.c*/2 prtstr()3 {4printf("Hello World!\n");5 }6 main()7 {8 prtstr();9 }test2.c中还是没有.h文件,编译仍可以顺利通过。
再把程序改动下:1/*test3.c*/2 main()3 {4prtstr();5 }67 prtstr()8 {9printf("Hello World!\n");10 }test3.c中仍然没有.h文件,编译失败→_→。
C语言主程序如何引用外部源代码中的函数
C语言主程序如何引用外部源代码中的函数在C语言中,要引用外部源代码中的函数,可以使用头文件和链接器来实现。
下面详细介绍这两种方法。
一、使用头文件:1. 创建一个包含函数原型的头文件(.h文件),命名为“extern_function.h”:```c#ifndef EXTERN_FUNCTION_H#define EXTERN_FUNCTION_H//声明外部函数extern int add(int a, int b);#endif```2. 在需要使用该函数的源代码文件中,使用`#include`预处理指令包含头文件:```c#include "extern_function.h"int maiint result = add(5, 3);printf("The result is: %d\n", result);return 0;```3.编译源代码文件时,将要引用的外部源代码文件一起编译:```$ gcc main.c external_code.c -o main```这样,编译器将把定义在"external_code.c"中的函数代码与引用它的源代码文件进行链接,使得在main函数中可以调用add函数。
二、使用链接器:1.将外部源代码文件编译为目标文件(.o文件):```$ gcc -c external_code.c -o external_code.o```2.在主程序源代码文件中声明外部函数:```cextern int add(int a, int b);```3.编译主程序源代码文件时```$ gcc main.c external_code.o -o main```链接器将把定义在external_code.o中的函数代码与主程序中引用它的源代码文件进行链接,使得在main函数中可以调用add函数。
总结:无论使用头文件还是链接器,引用外部源代码中的函数都需要将函数原型声明在引用该函数的源代码文件中。
extern的用法
extern的用法"extern" 是 C 和 C++ 语言中的一个关键字,用于声明外部变量和外部函数。
它的主要作用是在一个源文件中引用另一个源文件中定义的变量或函数。
当一个变量或函数在一些源文件中被使用,而其定义却在另一个源文件中时,就需要使用 "extern" 关键字来声明该变量或函数。
这是因为编译器默认情况下只会在当前源文件中查找相应的定义,如果找不到,就会报未定义错误。
为了解决这个问题,我们可以使用 "extern" 来告诉编译器在其他源文件中查找相应的定义。
下面,我们来详细讨论 "extern" 的用法及其在不同上下文中的使用情况。
1.声明全局变量:在一个源文件中声明变量,可以在其他源文件中使用该变量的值。
通常,全局变量的声明放在头文件中,而定义则放在相应的源文件中。
这样,其他源文件只需通过包含头文件即可使用全局变量。
```c// header.h// source1.cint globalVariable = 10;// source2.c#include "header.h"// 可以使用 globalVariable 变量```2.引用全局变量:在一个源文件中使用其他源文件中定义的全局变量,需要在使用之前进行声明。
这样,编译器就知道在其他源文件中查找相应的定义。
```c// source1.cint globalVariable = 10;// source2.c// 可以使用 globalVariable 变量```3.声明外部函数:在一个源文件中声明函数,可以在其他源文件中调用该函数。
同样,函数的声明通常放在头文件中,而定义则放在相应的源文件中。
```c// header.h// source1.cvoid externalFunctio//函数定义}// source2.c#include "header.h"// 可以调用 externalFunction 函数```4.引用外部函数:在一个源文件中调用其他源文件中定义的函数,需要在使用之前进行声明。
51单片机C语言中.c文件和.h文件的关联
1 方便开发:包含一些文件需要的共同的常量,结构,类型定义,函数,变量申明;
2 提供接口:对一个软件包来说可以提供一个给外界的接口(例如: stdio.h)。
2)h文件里应该有什么
常量,结构,类型定义,函数,变量申明。
3)h文件不应该有什么
变量定义, 函数定义。
{
unsigned int i,j;
for(j=n;j>0;j--)
for(i=112;i>0;i--);
}
在主程序main.c中
#i nclude <delay.h> //在主程序包含.h文件,不能包含.c文件
模块划分的"划"是规划的意思,意指怎样合理的将一个很大的软件划分为一系列功能独立的部分合作完成系统的需求。C语言作为一种结构化的程序设计语言,在模块的划分上主要依据功能(依功能进行划分在面向对象设计中成为一个错误,牛顿定律遇到了相对论),C语言模块化程序设计需理解如下概念:
(1)模块即是一个.c文件和一个.h文件的结合,头文件(.h)中是对于该模块接口的声明;
5)C51包含头文件方法
/eleclike/52862/message.aspx
4).c 和 .h文件的不同
/mfantastic/blog/item/d6fddd39793494f73a87ce0c.html
(2)某模块提供给其它模块调用的外部函数及数据需在.h中文件中冠以extern关键字声明;
(3)模块内的函数和全局变量需在.c文件开头冠以static关键字声明;
(4)永远不要在.h文件中定义变量!定义变量和声明变量的区别在于定义会产生内存分配的操作,是汇编阶段的概念;而声明则只是告诉包含该声明的模块在连接阶段从其料:
extern void c语言
extern void c语言C语言是一种通用的、高级的程序设计语言,被广泛应用于计算机软件开发领域。
它以其简洁、高效、可移植的特性而闻名,成为了许多程序员的首选语言。
本文将一步一步回答“外部函数声明”的问题。
外部函数声明是C语言中的一个重要概念,它可以使得函数可以在不同的源文件之间互相调用。
具体来说,当我们需要使用一个函数时,在调用函数之前,我们需要在当前文件中提供一个函数声明,以告诉编译器该函数的存在以及其参数和返回类型的声明。
这样编译器就可以正确处理函数的调用和返回。
下面我们将从以下几个方面来讲解外部函数声明:1. 利用头文件声明函数在C语言中,我们通常将函数的声明放置在头文件中。
头文件是一种包含函数原型以及变量和宏定义等信息的文件,它可以被多个源文件共享。
头文件一般以.h为后缀名,通过#include指令将其包含到源文件中即可使用其中的声明。
例如,我们有一个头文件math.h,其中包含了对一些数学函数的声明:c#ifndef MATH_H#define MATH_Hextern int add(int a, int b);extern int subtract(int a, int b);extern int multiply(int a, int b);#endif在需要使用这些函数的源文件中,我们通过以下方式来包含头文件并使用函数:c#include "math.h"int main() {int result = add(2, 3);printf("The result is: d\n", result);return 0;}这样,函数的声明就被正确地提供给了编译器,我们可以在源文件中调用这些函数。
2. 外部函数的定义与声明通常情况下,函数的定义和声明是分开的。
声明用于告诉编译器函数的存在以及其参数和返回类型的声明,而定义则是具体实现函数的地方。
extern的用法与h文件
(1)将全局变量在GlobalDefine.h中声明(declare):extern float x_tmp;注意:这时并不进行内存分配。
(2)在任何一个*.c的所有函数的外部定义(defination):float x_tmp= 0.5;注意:这时进行内存分配。
(3)在其它文件中包含GlobalDefine.h之后,就可以使用全局变量x_tmp了。
编译时,在此文件中遇x_tmp时,由于包含了GlobalDefine.h(即在此文件中进行了声明),因此编译器就知道这个变量已经在其它地方定义了,就不会报错。
连接时,连接器会将这个变量更换为在该变量定义时编译器给其分配的地址的指针。
因此,连接时连接器首先会在???中搜寻在该变量定义时编译器给其分配的地址,这时如果变量未定义或重复定义,连接器就会报错。
编译是以C文件为主体进行的,只要变量在这个文件中未重复定义,就不会报重复定义的错误,但是连接时会报错;如果变量使用extern进行了声明,或包含了有这样语句的h 文件,编译器就不会报变量未定义的错误。
常见错误:在main.c中定义了全局变量,在其它c文件中没有声明而直接访问。
这时会报变量未定义的错误。
规范做法:将上面。
常见错误:将变量定义写在h文件中,这样在多个文件包含此h文件时就会报变量重复定义的错误。
规范做法:只将变量定义写在h文件中,同时使用ifdef防止在当下这个c文件中变量被多次声明。
提示:●同一个变量可以在不同c文件中多次声明(为此可以在每个c文件中都包含GlobalDefine.h),在同一个c文件中多次声明也不报错;●在工程的所有文件中,同一个变量只能定义一次;●在任何c文件的函数之外定义的变量都是全局变量;●在任何c文件中调用的函数都需要声明(这一般是通过包含头文件实现的),但是可以在其他文件或库文件中定义。
如果函数在其他文件中定义了,但是在当下c文件中未声明,对于CodeWarrior,则不报错,但是相应函数的运行结果会出错。
C语言中关键词EXTERN解读
1基本解释:extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。
此外extern也可用来进行链接指定。
也就是说extern有两个作用,第一个,当它与"C"一起连用时,如:extern"C"void fun(int a,int b);则告诉编译器在编译fun这个函数名时按着C的规则去翻译相应的函数名而不是C++的,C++的规则在翻译这个函数名时会把fun这个名字变得面目全非,可能是fun@aBc_int_int#%$也可能是别的,这要看编译器的"脾气"了(不同的编译器采用的方法不一样),为什么这么做呢,因为C++支持函数的重载啊,在这里不去过多的论述这个问题,如果你有兴趣可以去网上搜索,相信你可以得到满意的解释!第二,当extern不与"C"在一起修饰变量或函数时,如在头文件中:extern int g_Int;它的作用就是声明函数或全局变量的作用范围的关键字,其声明的函数和变量可以在本模块活其他模块中使用,记住它是一个声明不是定义!也就是说B模块(编译单元)要是引用模块(编译单元)A中定义的全局变量或函数时,它只要包含A模块的头文件即可,在编译阶段,模块B虽然找不到该函数或变量,但它不会报错,它会在连接时从模块A生成的目标代码中找到此函数。
2问题:extern变量在一个源文件里定义了一个数组:char a[6];在另外一个文件里用下列语句进行了声明:extern char*a;请问,这样可以吗?答案与分析:1)、不可以,程序运行时会告诉你非法访问。
原因在于,指向类型T的指针并不等价于类型T的数组。
extern char*a声明的是一个指针变量而不是字符数组,因此与实际的定义不同,从而造成运行时非法访问。
应该将声明改为extern char a[]。
C语言中extern的用法(带有例子)
C语言中extern的用法在C语言中,修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。
1. extern修饰变量的声明。
举例来说,如果文件a.c需要引用b.c中变量int v,就可以在a.c中声明extern int v,然后就可以引用变量v。
能够被其他模块以extern修饰符引用到的变量通常是全局变量。
还有很重要的一点是,extern int v可以放在a.c中的任何地方,比如你可以在a.c中的函数fun 定义的开头处声明extern int v,然后就可以引用到变量v了,只不过这样只能在函数fun作用域中引用v罢了,这还是变量作用域的问题。
对于这一点来说,很多人使用的时候都心存顾虑。
好像extern声明只能用于文件作用域似的。
2. extern修饰函数声明。
从本质上来讲,变量和函数没有区别。
函数名是指向函数二进制块开头处的指针。
如果文件a.c需要引用b.c中的函数,比如在b.c中原型是int fun(int mu),那么就可以在a.c中声明extern int fun(int mu),然后就能使用fun来做任何事情。
就像变量的声明一样,extern int fun(int mu)可以放在a.c中任何地方,而不一定非要放在a.c的文件作用域的范围中。
对其他模块中函数的引用,最常用的方法是包含这些函数声明的头文件。
使用extern和包含头文件来引用函数有什么区别呢?extern的引用方式比包含头文件要简洁得多!extern的使用方法是直接了当的,想引用哪个函数就用extern声明哪个函数。
这大概是KISS原则的一种体现吧!这样做的一个明显的好处是,会加速程序的编译(确切的说是预处理)的过程,节省时间。
在大型C程序编译过程中,这种差异是非常明显的。
3. 此外,extern修饰符可用于指示C或者C++函数的调用规范。
比如在C++中调用C库函数,就需要在C++程序中用extern “C”声明要引用的函数。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
用#include可以包含其他头文件中变量、函数的声明,为什么还要extern关键字?如果我想引用一个全局变量或函数a,我只要直接在源文件中包含#include<xxx.h> (xxx.h包含了a的声明)不就可以了么,为什么还要用extern呢??这个问题一直也是似是而非的困扰着我许久,经过实践和查找资料,有如下总结:一、头文件首先说下头文件,其实头文件对计算机而言没什么作用,她只是在预编译时在#include 的地方展开一下,没别的意义了,其实头文件主要是给别人看的。
我做过一个实验,将头文件的后缀改成xxx.txt,然后在引用该头文件的地方用#include"xxx.txt"编译,链接都很顺利的过去了,由此可知,头文件仅仅为阅读代码作用,没其他的作用了!不管是C还是C++,你把你的函数,变量或者结构体,类啥的放在你的.c或者.cpp文件里。
然后编译成lib,dll,obj,.o等等,然后别人用的时候,最基本的gcc hisfile.cpp yourfile.o|obj|dll|lib 等等。
但对于我们程序员而言,他们怎么知道你的lib,dll...里面到底有什么东西?要看你的头文件。
你的头文件就是对用户的说明。
函数,参数,各种各样的接口的说明。
那既然是说明,那么头文件里面放的自然就是关于函数,变量,类的“声明”(对函数来说,也叫函数原型)了。
记着,是“声明”,不是“定义”。
那么,我假设大家知道声明和定义的区别。
所以,最好不要傻嘻嘻的在头文件里定义什么东西。
比如全局变量:/*xx头文件*/#ifndef _XX_头文件.H#define _XX_头文件.Hint A;#endif那么,很糟糕的是,这里的int A是个全局变量的定义,所以如果这个头文件被多次引用的话,你的A会被重复定义,显然语法上错了。
只不过有了这个#ifndef的条件编译,所以能保证你的头文件只被引用一次,不过也许还是不会出岔子,但若多个c文件包含这个头文件时还是会出错的,因为宏名有效范围仅限于本c源文件,所以在这多个c文件编译时是不会出错的,但在链接时就会报错,说你多处定义了同一个变量,Linking...incl2.obj : error LNK2005: "int glb" (?glb@@3HA) already defined in incl1.objDebug/incl.exe : fatal error LNK1169: one or more multiply defined symbols found注意!!!二、extern这个关键字真的比较可恶,在定义变量的时候,这个extern居然可以被省略(定义时,默认均省略);在声明变量的时候,这个extern必须添加在变量前,所以有时会让你搞不清楚到底是声明还是定义。
或者说,变量前有extern不一定就是声明,而变量前无extern就只能是定义。
注:定义要为变量分配内存空间;而声明不需要为变量分配内存空间。
下面分变量和函数两类来说:(1)变量尤其是对于变量来说。
extern int a;//声明一个全局变量aint a; //定义一个全局变量aextern int a =0 ;//定义一个全局变量a 并给初值。
int a =0;//定义一个全局变量a,并给初值,第四个等于第三个,都是定义一个可以被外部使用的全局变量,并给初值。
糊涂了吧,他们看上去可真像。
但是定义只能出现在一处。
也就是说,不管是int a;还是extern int a=0;还是int a=0;都只能出现一次,而那个extern int a可以出现很多次。
当你要引用一个全局变量的时候,你就必须要声明,extern int a; 这时候extern不能省略,因为省略了,就变成int a;这是一个定义,不是声明。
注:extern int a; 中类型int可省略,即extern a; 但其他类型则不能省略。
(2)函数函数,对于函数也一样,也是定义和声明,定义的时候用extern,说明这个函数是可以被外部引用的,声明的时候用extern说明这是一个声明。
但由于函数的定义和声明是有区别的,定义函数要有函数体,声明函数没有函数体(还有以分号结尾),所以函数定义和声明时都可以将extern省略掉,反正其他文件也是知道这个函数是在其他地方定义的,所以不加extern也行。
两者如此不同,所以省略了extern也不会有问题。
比如:/*某cpp文件*/int fun(void){return 0;}很好,我们定义了一个全局函数/*另一cpp文件*/int fun(void);我们对它做了个声明,然后后面就可以用了加不加extern都一样我们也可以把对fun的声明放在一个头文件里,最后变成这样/*fun.h*/int fun(void); //函数声明,所以省略了extern,完整些是extern int fun(void);/*对应的fun.cpp文件*/int fun(void){return 0;}//一个完整的全局函数定义,因为有函数体,extern同样被省略了。
然后,一个客户,一个要使用你的fun的客户,把这个头文件包含进去,ok,一个全局的声明。
没有问题。
但是,对应的,如果是这个客户要使用全局变量,那么要extern 某某变量;不然就成了定义了。
总结:对变量而言,如果你想在本源文件(例如文件名A)中使用另一个源文件(例如文件名B)的变量,方法有2种:(1)在A文件中必须用extern声明在B文件中定义的变量(当然是全局变量);(2)在A文件中添加B文件对应的头文件,当然这个头文件包含B文件中的变量声明,也即在这个头文件中必须用extern声明该变量,否则,该变量又被定义一次。
对函数而言,如果你想在本源文件(例如文件名A)中使用另一个源文件(例如文件名B)的函数,方法有2种:(1)在A文件中用extern声明在B文件中定义的函数(其实,也可省略extern,只需在A文件中出现B文件定义函数原型即可);(2)在A文件中添加B文件对应的头文件,当然这个头文件包含B文件中的函数原型,在头文件中函数可以不用加extern。
******************************************************************************* ***********************************************************************对上述总结换一种说法:(a)对于一个文件中调用另一个文件的全局变量,因为全局变量一般定义在原文件.c中,我们不能用#include包含源文件而只能包含头文件,所以常用的方法是用extern int a来声明外部变量。
另外一种方法是可以是在a.c文件中定义了全局变量int global_num ,可以在对应的a.h头文件中写extern int global_num ,这样其他源文件可以通过include a.h来声明她是外部变量就可以了。
(b)还有变量和函数的不同举例int fun(); 和 extern int fun(); 都是声明(定义要有实现体)。
用extern int fun()只是更明确指明是声明而已。
而 int a; 是定义extern int a; 是声明。
(3)此外,extern修饰符可用于C++程序中调用c函数的规范问题。
比如在C++中调用C库函数,就需要在C++程序中用extern “C”声明要引用的函数。
这是给链接器用的,告诉链接器在链接的时候用C函数规范来链接。
主要原因是C++和C 程序编译完成后在目标代码中命名规则不同。
C++语言在编译的时候为了解决的多态问题,会将名和参数联合起来生成一个中间的名称,而c语言则不会,因此会造成链接时找不到对应的情况,此时C就需要用extern “C”进行链接指定,这告诉编译器,请保持我的名称,不要给我生成用于链接的中间名。
三、extern和头文件的联系这种联系也解决了最初提出的2个问题:(a)用#include可以包含其他头文件中变量、函数的声明,为什么还要extern关键字?(b)如果我想引用一个全局变量或函数a,我只要直接在源文件中包含#include<xxx.h> (xxx.h包含了a的声明)不就可以了么,为什么还要用extern呢??答案:如果一个文件(假设文件名A)要大量引用另一个文件(假设文件名B)中定义的变量或函数,则使用头文件效率更高,程序结构也更规范。
其他文件(例如文件名C、D等)要引用文件名B中定义的变量或函数,则只需用#include包含文件B对应的头文件(当然,这个头文件只有对变量或函数的声明,绝不能有定义)即可。
******************************************************************************* *************************************************************那是一个被遗忘的年代,那时,编译器只认识.c(或.cpp)文件,而不知道.h是何物的年代。
那时的人们写了很多的.c(或.cpp)文件,渐渐地,人们发现在很多.c(或.cpp)文件中的声明变量或函数原型是相同的,但他们却不得不一个字一个字地重复地将这些内容敲入每个.c(或.cpp)文件。
但更为恐怖的是,当其中一个声明有变更时,就需要检查所有的.c(或.cpp)文件,并修改其中的声明,啊~,简直是世界末日降临!终于,有人(或许是一些人)再不能忍受这样的折磨,他(们)将重复的部分提取出来,放在一个新文件里,然后在需要的.c(或.cpp)文件中敲入#include XXXX这样的语句。
这样即使某个声明发生了变更,也再不需要到处寻找与修改了---世界还是那么美好!因为这个新文件,经常被放在.c(或.cpp)文件的头部,所以就给它起名叫做“头文件”,扩展名是.h.从此,编译器(其实是其中预处理器)就知道世上除了.c(或.cpp)文件,还有个.h的文件,以及一个叫做#include命令。