最近在看多文件编程的时候遇到的一个问题,本来以为理解了声明和定义的区别(然而并没有····),也算是重新认识了一次声明和定义,下面上代码

声明和定义:有分配空间的叫定义,没分配空间的叫声明

定义:表示创建变量或分配存储单元

声明:说明变量的性质,但并不分配存储单元

情形一:在源文件(.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语言的更多相关文章

  1. [转载]C++中声明与定义的区别

    C++学了这么多年你知道为什么定义类时,类的定义放在.h文件中,而类的实现放在cpp文件中.它们为什么能够关联到一起呢?你知道什么东西可以放在.h文件中,什么不能.什么东西又可以放在cpp文件中.如果 ...

  2. C++中声明与定义的区别

    如果是指变量的声明和定义: 从编译原理上来说,声明是仅仅告诉编译器,有个某类型的变量会被使用,但是编译器并不会为它分配任何内存.而 定义就是分配了内存.对于下面的两句代码:void Func(){in ...

  3. C++中声明和定义的区别

    声明 这有一个与这个名字相关的东西,并且它是这个类型的,告诉编译器我要使用它,并期待它定义在某一个地方. 定义 定义是指提供所有必要的信息(占用内存大小),使其能够创建整个实体. 我们必须明白的: 一 ...

  4. C\C++中声明与定义的区别

    声明和定义是完全同的概念,声明是告诉编译器"这个函数或者变量可以在哪找到,它的模样像什么".而定义则是告诉编译器,"在这里建立变量或函数",并且为它们分配内存空 ...

  5. C/C++头文件以及避免头文件包含造成的重定义方法

    C 头文件 头文件是扩展名为 .h 的文件,包含了 C 函数声明和宏定义,被多个源文件中引用共享.有两种类型的头文件:程序员编写的头文件和编译器自带的头文件. 在程序中要使用头文件,需要使用 C 预处 ...

  6. C语言中声明和定义详解(待看。。

    变量声明和变量定义 变量定义:用于为变量分配存储空间,还可为变量指定初始值.程序中,变量有且仅有一个定义. 变量声明:用于向程序表明变量的类型和名字. 定义也是声明,extern声明不是定义 定义也是 ...

  7. C++中的头文件(.h)和源文件(.cpp)都应该写什么?

    头文件(.h):写定义和声明写类的声明(包括类里面的成员和方法的声明).函数原型.#define常数等,但是一般来说不写具体的实现.注意: 1.在写头文件的时候需要注意,在开头和结尾处必须按照如下样式 ...

  8. [C] 如何使用头文件 .h 编译 C 源码

    在 C 语言中,头文件或包含文件通常是一个源代码文件,程序员使用编译器指令将头文件包含进其他源文件的开始(或头部),由编译器在处理另一个源文件时自动包含进来. 一个头文件一般包含类.子程序.变量和其他 ...

  9. [转]extern与头文件(*.h)的区别和联系

    用#include可以包含其他头文件中变量.函数的声明,为什么还要extern关键字? 如果我想引用一个全局变量或函数a,我只要直接在源文件中包含#include<xxx.h> (xxx. ...

随机推荐

  1. 无法启动 nexus 服务,错误1067:进程意外终止。java环境变量设置技巧。

    Nexus启动失败 wrapper.log记载: 无支持版本 51.0,版本51.0指的是Java1.7. 分析: nexus版本为2.14.8,适用JRE版本为1.7. 已配置JAVA_HOME为1 ...

  2. jQuery.extend 与 jQuery.fn.extend

    extend方法为jQuery对象的核心之一,语法如下: jQuery.extend([deep], target, object1, [objectN]),返回值Object. 概述:用一个或多个其 ...

  3. asp.net文件/大文件上传需要配置的项目整理

    HTTP 错误 404.13 - Not Found 请求筛选模块被配置为拒绝超过请求内容长度的请求. 最可能的原因: •Web 服务器上的请求筛选被配置为拒绝该请求,因为内容长度超过配置的值. 可尝 ...

  4. jQuery 新添加元素事件绑定无效

    jQuery中事件绑定,大多使用on就足够了. 但是对于新添加的元素 on 的绑定事件 会不起作用. 因为 append 中的 节点是在整个文档加载之后才添加的,页面并不会为未来的元素初始化添加点击事 ...

  5. echo不换行的实现

    1. echo的参数中, -e表示开启转义, /c表示不换行: echo -e "please input a value:/c" 2. -n不换行: echo -n " ...

  6. 小强学渲染之OpenGL渲染管线详析

    什么是OpenGL? OpenGL是一套图形硬件的软件API接口库,它直接和GPU交互,将3D场景渲染绘制到2D屏幕上.总结说,OpenGL的功能是将程序中定义的各种2D或3D模型绘制到帧缓存中,或者 ...

  7. 定时任务APScheduler

    安装 APScheduler $ pip install apscheduler 快速开始 from apscheduler.schedulers.blocking import BlockingSc ...

  8. Python开发【第七篇】:面向对象二

    字段 class Foo:     #静态字段(保存在类中)     CC = 123       def __init__(self):         #普通字段(保存在对象中)          ...

  9. swift static func 和 class func

    Swift中static func 相当于class final func.禁止这个方法被重写 clas func  可以被继承重写

  10. 自定义View(四) ViewGroup 动态添加变长Tag标签 支持自动换行

    欲实现如下效果: 思路很简单就2步: 1.测量出ViewGroup的大小 2.找出子View的位置 若要实现动态添加标签view,就要实现ViewGroup的onMeasure().onLayout( ...