C语言声明与定义的区别
转自:https://blog.csdn.net/gatieme/article/details/50640424
C++程序通常由许多文件组成,为了让多个文件访问相同的变量,C++区分了声明和定义。
变量的定义(definition)用于为变量分配存储空间,还可以为变量指定初始值。在程序中,变量有且仅有一个定义。
声明(declaration)用于向程序表明变量的类型和名字。定义也是声明:当定义变量的时候我们声明了它的类型和名字。可以通过使用extern声明变量名而不定义它。不定义变量的声明包括对象名、对象类型和对象类型前的关键字extern。
extern声明不是定义,也不分配存储空间。事实上它只是说明变量定义在程序的其他地方。程序中变量可以声明多次,但只能定义一次。
只有当声明也是定义时,声明才可以有初始化式,因为只有定义才分配存储空间。初始化式必须要有存储空间来进行初始化。如果声明有初始化式,那么它可被当作是定义,即使声明标记为extern。
任何在多文件中使用的变量都需要有与定义分离的声明。在这种情况下,一个文件含有变量的定义,使用该变量的其他文件则包含该变量的声明(而不是定义)。
如何清晰的区分变量声明和定义
extern通知编译器变量在其他地方被定义
1.extern告诉编译器变量在其他地方定义了。
例如:
extern int i; //声明,不是定义
int i; //声明,也是定义,未初始化
- 1
- 2
带有初始化式的声明必定式定义
2.如果声明有初始化式,就被当作定义,即使前面加了extern。
只有当extern声明位于函数外部时,才可以被初始化。
例如:
extern double pi=3.141592654; //定义
- 1
函数的声明和定义
3.函数的声明和定义区别比较简单,带有{ }的就是定义,否则就是声明。
例如:
extern double max(double d1,double d2); //声明
- 1
除非有extern关键字,否则都是变量的定义。
4.除非有extern关键字,否则都是变量的定义。
例如:
extern int i; //声明
int i; //定义
- 1
- 2
程序模块化设计风格
概要
1. 不要把变量定义放入.h文件,这样容易导致重复定义错误。
永远不要在.h文件中定义变量。定义变量和声明变量的区别在于定义会产生内存分配的操作,是汇编阶段的概念;而声明则只是告诉包含该声明的模块在连接阶段从其它模块寻找外部函数和变量
2. 尽量使用static关键字把变量定义限制于该源文件作用域,除非变量被设计成全局的。
3. 可以在头文件中声明一个变量,在用的时候包含这个头文件就声明了这个变量。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
模块化要点
(1) 模块即是一个.c文件和一个.h文件的结合,头文件(.h)中是对于该模块接口的声明;
(2) 某模块提供给其它模块调用的外部函数及数据需在.h中文件中冠以extern关键字声明;
(3) 模块内的函数和全局变量需在.c文件开头冠以static关键字声明;
(4) 永远不要在.h文件中定义变量!定义变量和声明变量的区别在于定义会产生内存分配的操作,是汇编阶段的概念;而声明则只是告诉包含该声明的模块在连接阶段从其它模块寻找外部函数和变量。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
一般情况下头文件中只放变量的声明,因为头文件要被其他文件包含(即#include),如果把定义放到头文件的话,就不能避免多次定义变量,C++不允许多次定义变量,一个程序中对指定变量的定义只有一次,声明可以无数次。
不过有三个例外,一下三中实体的定义也可放到头文件中。
1.值在编译时就已知的const 变量的定义可以放到头文件中
如:const int num(10);
2.类的定义可以放到头文件中
3.inline 函数
- 1
- 2
- 3
- 4
这三个实体可以定义在多个源文件中,只要在每个源文件中的定义相同。
示例程序
#include <stdio.h>
#include <stdlib.h>
// 是定义,定义了A为整型的外部变量
// C中定义的变量默认就是extern的,
// 因此一般来说int a = 10 <==> extern int a = 10;
/*extern */int a = 10;
//如果声明有初始化式,就被当作定义,即使前面加了extern。
//只有当extern声明位于函数外部时,才可以被初始化。
int main(void)
{
extern int a; // 声明一个外部extern的int型变量a
// 这是个声明而不是定义,声明A是一个已经定义了的外部变量
// 注意:声明外部变量时可以把变量类型去掉如:extern a;
printf("a = %d\n", a);
return EXIT_SUCCESS;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
在这个程序中,我们再函数外部定义了一个变量
注extern int a = 10;只有当extern声明位于函数外部时,才可以被初始化。
我们后面还会提到这个问题
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int a; // 定义一个变量, 不初始化
int b = 10; // 定义一个变量, 同时进行初始化
extern int c; // 声明一个外部extern的int型变量a
printf("a = %d\n", a);
printf("b = %d\n", b);
printf("c = %d\n", c);
extern int d = 10;
return EXIT_SUCCESS;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
在这个程序中,
int a;是个定义,但是未初始化,打印他的值式不确定的,因此编译时会报未初始化的异常。
int b = 10; 是个定义,并且被正确初始化,打印b的值没有问题。
但是是个声明,如果要对c进行读写操作,而我们并没有对c进行定义,因此语法检查没有问题,但是在链接时,连接器会找不到c的地址。
对于d再明显不过了,前面我们提到过如果声明有初始化式,就被当作定义,即使前面加了extern。但是只有当extern声明位于函数外部时,才可以被初始化。
现在这个定义很明显被gcc编译器认为是错误的。
C语言声明与定义的区别的更多相关文章
- 在源文件(.c)和头文件(.h)中声明和定义的区别——C语言
最近在看多文件编程的时候遇到的一个问题,本来以为理解了声明和定义的区别(然而并没有····),也算是重新认识了一次声明和定义,下面上代码 情形一:在源文件(.c)中 相信大部分读者对声明和定义的理解是 ...
- PHP中变量声明和定义的区别
先记录一下(不知道PHP是不是一样,但是C语言是这样的):把建立空间的声明称之为“定义”,而把不需要建立存储空间的声明称之为“声明”.声明的最终目的是为了提前使用,即在定义之前使用,如果不需要提前使用 ...
- [转载]C++中声明与定义的区别
C++学了这么多年你知道为什么定义类时,类的定义放在.h文件中,而类的实现放在cpp文件中.它们为什么能够关联到一起呢?你知道什么东西可以放在.h文件中,什么不能.什么东西又可以放在cpp文件中.如果 ...
- C++ 变量的声明与定义的区别
变量声明和定义的区别 我们在程序设计中,时时刻刻都用到变量的定义和变量的声明,可有些时候我们对这个概念不是很清楚,知道它是怎么用,但却不知是怎么一会事,下面我就简单的把他们的区别介绍如下:(望我的指点 ...
- C++之声明与定义的区别
直接举例,在C++中,声明与定义的区别如下: extern int a;//若有extern关键字,则只是声明 int b;//若没有extern关键字,则为声明+定义 int a;//若之前已经声明 ...
- 【非原】c语言之声明和定义的区别
原创地址:http://www.cnblogs.com/haore147/p/3647466.html 什么是定义?什么是声明?它们有何区别? 举个例子: 1 2 A)int i; B)extern ...
- 陈正冲老师讲c语言之声明和定义的区别
什么是定义?什么是声明?它们有何区别? 举个例子: A)int i; B)extern int i;(关于extern,后面解释) 哪个是定义?哪个是声明?或者都是定义或者都是声明?我所教过的学生几乎 ...
- 浅谈声明与定义的区别 分类: C/C++ 2015-06-01 15:08 157人阅读 评论(4) 收藏
以下代码使用平台是VS2012. 清楚明白声明与定义是一名合格的程序猿的基本要求. 本人认为,C++编码过程中谈及"声明"和"定义"是因为我们要使用一个变量.类 ...
- [转载]C++声明和定义的区别
<C++Primer>第四版 2.3.5节中这么说到: ①变量定义:用于为变量分配存储空间,还可为变量指定初始值.程序中,变量有且仅有一个定义. ②变量声明:用于向程序表明变量的类型和名字 ...
- [C/C++] C++声明和定义的区别
·变量定义:用于为变量分配存储空间,还可为变量指定初始值.程序中,变量有且仅有一个定义. ·变量声明:用于向程序表明变量的类型和名字. ·定义也是声明:当定义变量时我们声明了它的类型和名字. ·ext ...
随机推荐
- 空间数据格式(地理数据格式):GeoJSON(FeatureCollection)与EsriJSON(FeatureSet/ArcGIS格式)
一.FeatureCollection(GeoJSON)格式介绍 https://learn.microsoft.com/en-us/javascript/api/azure-maps-control ...
- windows 服务 包装模板
github地址: https://github.com/xl711436/Xiaolei.MockService 在 MockServiceInstance.cs 中 对应的方法中添加 对应的逻辑 ...
- svn 报 is not a working copy 错误
当时提交代码 svn 报 is not a working copy ,上网查找问题 要我重新拉代码下来 然后放进修改的代码重新提交,我觉得很不合理,我看了下我提交的代码文件有80多个,我在想是否 ...
- centos7 python设置虚拟环境
virtualenv 是一个可以在同一计算机中隔离多个python版本的工具.有时,两个不同的项目可能需要不同版本的python,如 python2.6.6 / python3.0 ,但是如果都装到一 ...
- 19c 滚动升级
一.环境说明 节点1 节点2 IP 192.168.3.77 192.168.3.88 DB 版本 Oracle 19.6.0.0.0 Oracle 19.6.0.0.0 OS 主机名 oadb1 ...
- Chrome(谷歌浏览器)安装Vue插件vue-devtools
安装步骤如下:1.首先给大家提供一个git地址,虽然官网也有地址(https://github.com/vuejs/vue-devtools.git),我认为不太好用给大家提供另一个git地址: ht ...
- drf从入门到飞升仙界 07
认证组件 ## 认证组件逻辑 # 1.登录认证的限制: - 访问接口,有的需要登陆后才能访问,有的接口,不登录就能访问 # 2.准备: -User表 : 存储用户名,密码 -UserToken表:存储 ...
- 备份是个好习惯 bugku
题目描述: 解题思路: 1.查看网页源码只显示一行字符,有点像16进制,但经过解码并不是,也不是base64等编码 2.根据题目,应该和备份相关,默认页面一般都是 index.php或者index ...
- nginx增加自定义账号鉴权
nginx增加自定义账号鉴权 使用nginx反向代理实现 当一个站点内部程序是个黑盒(无法修改里面的请求逻辑),如何增加自己的账号系统鉴权 实现逻辑 使用nginx的反向代理功能 自定义账号系统增加两 ...
- ES6的模块化(import引入)
先做个前提,新建三个模块JS文件m1,m2,m3,其中m1.js 为分别暴露,m2.js 为统一暴露,m3.js 为默认暴露.接下来进行文件的import引入 1.通用的引入方式,这种方式适合任何暴露 ...