在源文件(.c)和头文件(.h)中声明和定义的区别——C语言
最近在看多文件编程的时候遇到的一个问题,本来以为理解了声明和定义的区别(然而并没有····),也算是重新认识了一次声明和定义,下面上代码
声明和定义:有分配空间的叫定义,没分配空间的叫声明
定义:表示创建变量或分配存储单元
声明:说明变量的性质,但并不分配存储单元
情形一:在源文件(.c)中(函数内)
int a;//定义
extern int a;//声明
第一个int a是定义,分配了存储空间(其实包括了声明和定义两个步骤,可以叫"定义性声明"),第二个 extern int a是声明(也叫"引用性声明"),没有分配存储空间
关于extern的使用,感兴趣的读者可以看一下另一片随笔:extern的使用详解(多文件编程)——C语言
声明可以多次,定义只能有一次
意思是在源文件(.c)中可以多次声明同一个变量,例如
在编译阶段是不会报错的
情形二:在源文件(.c)中(函数外)

编译结果:

这里的int a;放在函数外,没有出现重定义的错误,并不意味着int a就不是定义了,int a仍然是定义,编译阶段没有报错了原因在于全局变量没有赋初值,没赋初值的全局变量,那么在目标文件中是不会为
这个全局变量分配空间的,它被放在BSS段(如果是赋初值的全局变量,那么放在data段),BSS段在目标文件中是没有的(这个就是编译阶段不会报错的原因),意味着没赋初值的全局变量不占磁盘空间,
当程序加载运行时,就会为bss段中的数据分配内存进行初始化了(起到了节省磁盘空间的作用),上面说了BSS段的数据不占磁盘空间,那么它的大小和符号存在哪呢? bss段占据的大小存放在ELF文件格式
中的段表(Section Table)中,段表存放了各个段的各种信息,比如段的名字、段的类型、段在elf文件中的偏移、段的大小等信息
(感谢园友:SD8086 指出随笔中的错误)
(对内存映像感兴趣的读者可以看下这两篇文章:bss段不占据磁盘空间的理解、大内高手—全局内存)
情形三:在头文件(.h)中
在头文件中的声明和定义和在源文件中函数外的声明和定义相同,下面为测试结果



修改头文件后



从上面可以看出int a在头文件中仍然是定义,只不过和全局变量定义相同,只要没有赋初值,编译阶段就不会报错
在源文件(.c)和头文件(.h)中声明和定义的区别——C语言的更多相关文章
- [转载]C++中声明与定义的区别
C++学了这么多年你知道为什么定义类时,类的定义放在.h文件中,而类的实现放在cpp文件中.它们为什么能够关联到一起呢?你知道什么东西可以放在.h文件中,什么不能.什么东西又可以放在cpp文件中.如果 ...
- C++中声明与定义的区别
如果是指变量的声明和定义: 从编译原理上来说,声明是仅仅告诉编译器,有个某类型的变量会被使用,但是编译器并不会为它分配任何内存.而 定义就是分配了内存.对于下面的两句代码:void Func(){in ...
- C++中声明和定义的区别
声明 这有一个与这个名字相关的东西,并且它是这个类型的,告诉编译器我要使用它,并期待它定义在某一个地方. 定义 定义是指提供所有必要的信息(占用内存大小),使其能够创建整个实体. 我们必须明白的: 一 ...
- C\C++中声明与定义的区别
声明和定义是完全同的概念,声明是告诉编译器"这个函数或者变量可以在哪找到,它的模样像什么".而定义则是告诉编译器,"在这里建立变量或函数",并且为它们分配内存空 ...
- C/C++头文件以及避免头文件包含造成的重定义方法
C 头文件 头文件是扩展名为 .h 的文件,包含了 C 函数声明和宏定义,被多个源文件中引用共享.有两种类型的头文件:程序员编写的头文件和编译器自带的头文件. 在程序中要使用头文件,需要使用 C 预处 ...
- C语言中声明和定义详解(待看。。
变量声明和变量定义 变量定义:用于为变量分配存储空间,还可为变量指定初始值.程序中,变量有且仅有一个定义. 变量声明:用于向程序表明变量的类型和名字. 定义也是声明,extern声明不是定义 定义也是 ...
- C++中的头文件(.h)和源文件(.cpp)都应该写什么?
头文件(.h):写定义和声明写类的声明(包括类里面的成员和方法的声明).函数原型.#define常数等,但是一般来说不写具体的实现.注意: 1.在写头文件的时候需要注意,在开头和结尾处必须按照如下样式 ...
- [C] 如何使用头文件 .h 编译 C 源码
在 C 语言中,头文件或包含文件通常是一个源代码文件,程序员使用编译器指令将头文件包含进其他源文件的开始(或头部),由编译器在处理另一个源文件时自动包含进来. 一个头文件一般包含类.子程序.变量和其他 ...
- [转]extern与头文件(*.h)的区别和联系
用#include可以包含其他头文件中变量.函数的声明,为什么还要extern关键字? 如果我想引用一个全局变量或函数a,我只要直接在源文件中包含#include<xxx.h> (xxx. ...
随机推荐
- PHP json_encode 文本形式数字下标数组导致下标丢失
$arr = array( '0'=>'a','1'=>'b','2'=>'c','3'=>'d' ); echo json_encode($arr); 但是结果是 [&quo ...
- python如何打开一个大文件?
with open('a.csv','r') as f: for i in f: print(i) while True: a = f.readline() if not a: break f.rea ...
- 尚硅谷springboot学习27-使用外置servlet容器
嵌入式Servlet容器:应用打成可执行的jar 优点:简单.便携: 缺点:默认不支持JSP.优化定制比较复杂(使用定制器[ServerProperties.自定义EmbeddedServle ...
- json 异常
com.google.gson.JsonSyntaxException: 1530842820000 1530842820000 是服务器直接返回的Date值由 Gson 解析后出来的值. 后台发出: ...
- Linux下MySQL5.7.18 yum方式从卸载到安装
本文出处:http://www.cnblogs.com/wy123/p/6932166.html 折腾了大半天,看了想,想了看,总算是弄清楚yum安装的过程了,之前写过二进制包安装的,这里用yum安装 ...
- int和string之间的转换
#include<cstring> #include<algorithm> #include<stdio.h> #include<iostream> # ...
- 伪类+js实现CSS3 media queries跨界准确判断
@media screen and (min-width: 45em) { body:after{ content:"宽屏" } } var content = window.ge ...
- 算法练习LeetCode初级算法之字符串
反转字符串 我的解法比较low,利用集合的工具类Collections.reverse反转,用时过长 class Solution { public void reverseString(char[] ...
- React createRef:引用
一 代码 import React, { Component } from 'react'; class Box extends Component { render() { return <b ...
- Web前端(整理不好,自己未学)
1.公司招聘信息 (1)小公司 (2)腾讯 ①社会招聘 ②校园招聘 (3)百度 ①社会招聘 ②实习 ③校园招聘 2.岗位要求 开发经验,良好的编程习惯,学习能力,至少二个项目开发设计,具备需求功能模块 ...