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

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

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

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

情形一:在源文件(.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. leetcode55

    bool canJump(vector<int>& nums) { ]; ; i < nums.size() && reach >= i; i++) { ...

  2. Python正则替换字符串函数re.sub用法示例(1)

    本文实例讲述了Python正则替换字符串函数re.sub用法.分享给大家供大家参考,具体如下: python re.sub属于python正则的标准库,主要是的功能是用正则匹配要替换的字符串然后把它替 ...

  3. linux 机器之间 zssh, rz, sz互相传输

    zssh的全名叫ZMODEM SSH.看名字就知道,使用的zmodem,我们习惯了SecureCRT,直接就可以用来发送文件,比使用scp方便很多. zmodem协议方便主要表示在以下点 其一,不需要 ...

  4. MySQL存储过程定义中的特性(characteristic)的含义

    MySQL的存储过程蛮啰嗦的,与MSSQL或者Oracle的存储过程相比,如果没有显式指定,他会隐含地指定一系列特性(characteristic)的默认值来创建存储过程 通常在使用图形界面工具进行存 ...

  5. redis 动态修改配置与备份文件目录

    redis-cli -c -h 10.1.1.1 -p 7000 获取所有可以配置的KEY config get * 设置KEY config set * 配置重新写入配置文件 CONFIG REWR ...

  6. 数据库常用操作(mysql)

    创建 create database 库名 create table 表名(列名 type(varchar(size),int(size),decimal(size,d))) "size&q ...

  7. 网络文件系统NFS

    NFS介绍 什么是NFS? NFS是Network File System的缩写,即网络文件系统.它的主要功能是通过网络(一般是局域网)让不同的主机系统之间可以共享文件或目录.NFS客户端(一般为应用 ...

  8. springboot和mybatis之thymleaf整合简单插入用户数据

    编写mapper接口和对应的mapper.xml文件,注意对应的注解 @Mapper @Repository public interface StudentMapper { void insertS ...

  9. KO ----- 静态资源404问题

    --------------------siwuxie095                                 KO ----- 静态资源 404 问题         在 Spring ...

  10. 【python原理解析】gc原理初步解析

    python的gc是会用到:引用计数.标记-清除和分代收集,首先说明一下什么是引用计数 可以通过sys模块中的getrefcount()方法获取某个对象的引用计数 python本身的数据类型有基础类型 ...