实型变量是存储实型java常量和变量的区别的存储单元?

您现在的位置: &
考点5:实型数据
全国计算机等级考试通关宝典:二级C语言程序设计(2014版)_考点5:实型数据
2.3.5 &考点5:实型数据  实型常量又称实数,在C语言中可以用两种形式表示一个实型常量:小数形式和指数形式。  (1)小数形式。其表现形式是包含一个小数点的十进制数字串,小数点的前面或后面可以没有数字,但不能同时没有数字。  (2)指数形式。其格式由两部分组成:一部分是十进制小数形式或十进制常量部分,另一部分为指数部分。指数部分是在e或者E后跟整数阶码(即可带符号的整数)。  C语言中的实型变量分为单精度型和双精度型两类,分别用类型名float和double进行定义。在一般的计算机系统中,为float类型的变量分配4字节的存储单元,为double类型..
&&&主编推荐
&&&最新图书
&&&最新视频
&&&热门试卷
& & & & & & & &当前位置: >>
C语言数据类型 常量与变量
1.第二节 常量与变量一、常量和符号常量1、常量: 在程序运行过程中,其值不能被改变的量 常量区分为不同类型,如 12、3.2、'a' 2、符号常量: 用一个标识符代表的一个常量 定义方法: #define 标识符 常量 习惯上,符号常量名用大写,变量用小写跳转到第一页常量区分为不同类型,如 12、3.2、'a',是按书写形式来 区分它的类型,如 12、3.2、'a',中 12 就是整型、3.2 就 是实型, ‘a?就是字符型。 2、符号常量: 用一个标识符代表的一个常量 定义方法: #define 标识符 常量 是用一个预处理命令宏定义来定义的,这在书中第 9 章将 会讲到,后面我们也会再讲。2.我们曾经在第一章已经讲过,C 语言的数据结构非常 丰富,它是以数据类型的形式出现的,包括整型、实型、 字符型、数组、指针、结构体和联合体等,我们要编程序, 就是要对这些数据类型进行操作,操作步骤就是算法,而 这操作步骤必须以一种结构化程序设计方法来实现,算法 和结构化程序设计方法我们会在四、五、六章进行详细讲 解。那用什么来表达这个操作过程呢?我们这里用的语言 工具就是 C 语言,所用的环境就是 Turbo C 2.0。3. 1.2】求和 【例main() { int a,b, a=1; b=2; sum=a+b; printf(“sum is %d\n”,sum); }4.大家来看第一章中我们举的第二个例子,在这求和程 序中,首先我们进行了变量 a,b,sum 的定义,定义 a,b,sum 为整型变量,在程序中对用到的所有数据都必须指定其数 据类型;在程序后面就是对这三个整型变量进行操作,操 作步骤就是先对 a、 b 赋值,然后再进行 a+b 计算,然后 把 a+b 计算的结果赋值给 sum 变量, 最后用 printf 函数把 求和结果输出到显示器显示,这些操作步骤就是算法,它 有先后顺序的,不能是先求 a+b,再对 a、 b 赋值;这里 用的程序设计方法是顺序结构; 当然语言工具就是 C 语言, 环境就是 Visual C++6.0。1 常量是其值不随程序的运行而改变的量,常量 现在我们就来列一下 C 的数据类型有哪些,当然大分为整型常量、实型常量和字符型常量,这在后面 家先不要去记它,先给大家有一个整体印象,等我们这我们要具体讲到。变量是其值可随程序的运行而改 本书都学完了,大家也就自然记住了。它分为基本类型、 第二节 常量与变量 变的量。在程序中我们要经常定义变量,并对其进 派生类型、指针型和空类型,派生类型是基本型的导出行操作,而程序中的变量在计算机中是如何操作的 一、 常量:其值不随程序的运行而改变的量 类型,例如整型数组类型就是按照一定顺序集合的整型呢?首先我们要给变量起个变量名,通过变量名计 二、 变量:其值可随程序的运行而改变的量 数据,我们这一章主要讲基本类型,在以后章节里会陆算机自动给分配内存地址,也就是给分配存储单元, 变量名 续讲派生类型、指针型和空类型。这一章基本类型包括然后在存储单元中存入或取出数据,也就是变量值, 标识符 a 整型、 字符型、 变量值 实型。 整型包括短整型 short、 基本型 int、 特别要注意的是变量名和变量值的区别,变量名对 8 无符号型 unsigned 和长整型 实型也叫浮点型包括应的是内存地址,而变量值所对应的是内存中地址 存储单元 单精度 float 和双精度 double 型。 中存放的内容。数据在计算机中如何运行,在以后 注意:变量名和变量值的区别 课程的微机原理中会详细讲述,到那时候同学们会 写出效率更高的程序。这里我们要讲讲如何给变量 对应内存地址 内存地址中存放的内容 跳转到第一页 或文件等等起名字,也就是标识符。 6. 三、 标识符 ※ 标识符就是给程序中的变量、常量、 函数、数组、结构体以及文件所起的名字。其命名规则有 5 点,它是 1.命名规则: (1) 以字母或下划线开头,由字母、数字 和下划线组成;例:month li1_1 (2)不能和系统关键字同名;例:short (3)尽量不要用下划线开头;例:_total 这是正确的标识符,但是不提倡。 (4)一般长度不超过 8 个字符;因为各个系统规定的标识符长度不一样,为了程序容易移值到它机器或 系统中运行而不出现标识符错误,因此建议大家定义标识符时,一般长度不超过 8 个字符。 (5)大小写是不同的字母。例:Student student 是不一样的标识符。5.7.2 .好的命名习惯: (1)尽量做到见名知意; (sum,area) (2)变量名、函数名用尽量用小写;习惯上变量名定义成为小写字母,而完全大写字母一般定义为常量。(3)在易混淆地方,尽量避免用易认错的字母; 0(数字) O(大写字母) o(小写字母) 1 (数字) I(I 的大写字母) l(L 的小写字母) 2 (数字)Z(大写字母) z(小写字母)例如:no 与 n0、ll 与 11 特别是大写的 I 与小写的 L,一般人很难给它区别开,因此会造成阅读程序的困 难,大家一定要注意这一点。8.第四点我们讲讲变量的使用:四、变量的使用 1、 先定义 2、 后赋初值 3、再改变变量的值 “先定义,后使用” : 有三点好处。 ? 保证变量名正确使用; ? 方便了变量的内存单元分配; ? 便于语法检查。2 9.我们举个简单例子说明,【例 3.2】求余数 main() { float a,b, a=1.0; c=2.0; rem=a%b; printf(“rem is %f\n”,rem); }这个程序我们就采用了“先定义,后使用”的规则,但在这 个程序中存在 2 个错误,大家看出来没有。首先变量使用错误, 定义的是 a,b,rem 变量,而我们使用的是 a,c,rem 变量 ,其次 是求余运算两边只能是整型变量, 而这里用的是实型变量, 因此 通过编译就能检查出语法错误。 并且内存会根据你所定义的变量 类型给分配内存单元字节数,a,b,rem 是实型变量内存各给分配 4 个字节的内存单元。让系统合理地安排内存单元的使用。现在我们分别来讲讲整形、实型和字符型数据:10.整形数据分为整型常量和整型变量,整型常量包括十 进制,八进制和十六进制,十进制就以我们平时阿拉伯数 字表示就行;而八进制的表示是以数字 0 开头,例如 012 表示的八进制就是十进制的 10; 而十六进制是以数字 0 加 小写字母 x 开头的,例如 0x36 表示的是十进制的 6+16*3 等于 54。大家知道八进制、十六进制和十进制之间的换算 吗?它们都是如何表示的?如果课讲完有时间剩余我会给 同学们补一下这方面知识。在实际编程时十六进制是很有 用的。 整型变量包括基本型 int、 短整型 short、 长整型 long 和无符号型 unsigned。11.我们看看这张表格,整型数据的取值范围,以及占内存的字节数。在 Turbo C 整型定义中, 基本型与短整型字节 数是一样,占 2 个字节,长整型占字节数多一倍, 占 4 个字节数,取值范围,大家可以看一下,长整 型比基本型能大出很多,达到负 21 亿到正 21 亿, 这个取值范围足够用了。 各个系统各个类型之间所 占字节数经常是不一样的,但一定遵循一个规则, 就是 short 小于或等于 int 型,而 int 小于或等于 long 型, 基本型所占的字节数有的系统与短整型一 致,有的系统是与长整型一致,同学们用别的系统 时,一定要看系统手册的定义,这里我们列的是 TURBO C 的标准。有符号型与无符号型的取值范 围正好差一倍,这与符号位有关系,大家看这个例 子3 12.整型和无符号整型都是 2 个字节, 位二进制 16 数, 在内存单元中定义为整型变量那么它的首位 被定义为符号位,不能被数据使用,因此它的最 大值只能是 2 的零次方一直加到 2 的 14 次方等 于 32767,符号位 0 代表正数,1 代表负数;而 无符号整型变量首位就可以存储数据, 因此它的 最大值比整型变量大一倍, 它的值是从 2 的 0 次 方加到 2 的 15 次方。从这一个例子我们就知道 短整型、 长整型和其它无符号型的取值范围是如 何计算而来的了。这里就不一一计算,同学们回 去可以自己计算一下。13.现在我们来举一个例子来说明整型数据的定义与溢出, 整型变量的定义我们已经用了很多了,如果是定义基本型, 我们就写 int A,B 如果是定义长整型我们应该怎么写?对 了,写 long A,B;短整型就是写 short A,B; ,定义变量一 般在声明部分进行。好,我们再来看看溢出的问题,因为我 们整型变量取值最大就是 32767,这时我们让它加 1 赋值给 整型变量 B,会出现什么现象呢?对了,会产生溢出,它的 运行结果会出什么现象呢?A 变量的值是 32767,因为没有 超出取值范围,因此输出没有错;但是 B 的输出就与实际不 符了, 这就产生了溢出现象, 可是这种错误运行时并不报错, 这种现象在我们调试 C 程序过程中会经常出现,这就是 C 语言的灵活给我们带来的副作用,因此要求程序员的细心和 经验才能保证我们结果的正确性。这时我们应该怎样修改此 程序呢?对了只要对 B 定义成长整型就可以了, 这时运行的 结果就正确了。14.作为学习 C 语言来讲,我们必须稍微了解数据在内存中 是如何存储的,实际上数据在内存中是以补码形式存储的, 正数的补码就是它本身,而负数的补码是按这种规则来求 的,大家要记住,按位取反,未位加 1。大家看,A 变量中 存储的二进制代码就是 32767,A 加 1 赋值给变量 B,大家 看在二进制加法运算是没有错,确实等于 1 后面 15 个 0,那 么这个数就是-32768 的补码形式,大家回去后可以用这种方 法推算一下。我们这里举个得意的例子,-14 在内存中的存 放形式,首先取它绝对值 14 的原码,然后按位取反,1 变成 0,0 变成 1,取反后加 1,好这个 16 位二进制数就是-14 的 补码。 如果我们最后有剩时间, 我们在课堂给大家推推-32768 的补码。4 15.在程序中实型常量有两种表示形式, 第一种是十进 制形式,由数字和小数点组成,例如 123.1 或.123 或 123.,其中小数点是不可惑缺的,必须写,这一点同 学们一定要注意, 很多同学在写程序过程中在此范错 误。另外一种形式就是指数形式,写时字母 E 前必 须有数字,字母后必须是整数,例如 123E3,当然实 型常量在计算机内存中都是以指数形式来存放, 如何 存的自己可以看书, 我们这里就不讲了。 实型变量有 三种形式,即单精度 FLOAT 型,双精度 DOUBLE 型,及长双精度 LONG DOUBLE 型。16.大家看一下这张表格,一般情况下单精度型 FLOAT 的取值范围已经足够用了,当长双精度类型 目前为止我们用不上, 一般不考虑它。 在应用 FLOAT 型和 DOUBLE 型时,取值范围我们是足够用的,主 要是考虑有效数位, 如果我们需要精度高那么我们就 定义 DOUBLE 型,这样会以降低运算速度为代价, 如果精度要求不太高,那么 FLOAT 型已经足够用, 有效数位保留 6 到 7 位, 如果系统在运行实型常数运 算, 一般默认双精度型进行运算, 如果想提高运算精 度可在需要运算的数据后加字母 F,那么它就以 FLOAT 型进行运算。17.现在我们看看在实型数据运算时所要注意的问题, 因 有效字位数有限,经常在运算过程中都需要进行四舍五 入来得到结果,那么经常就会发生一定的误差,以来同 学们在具体应用过程中,不可能出现这种、那种问题, 这都得经过实践,慢慢总结出经验才能避免,大家看一 个例子,定义两个变量 A、B 为 FLOAT 型,并对 A 进行 赋值,然后进行运算,把 A 加上 20 赋值给 B,这时我们 在显示器上输出 A、B 值,这时我们会发现 A、B 值相 等,A 的值并没有加 20 赋给 B,而是把 A 值直接赋给 B 了,这是怎么回事?就是因为单精度型的有效数位是 7 位造成的,B 的值只能保证七位有效数位数值的准确, 而后面几位就不能保证了,所以造成了这种结果。解决 的办法就是把 FLOAT 型改成 DOUBLE 型就可以了,以 后编程一定要注意这种情况,因为系统不会给你查出这 种错误,因此遇到这类问题一定要十分注意,才能保证 5 结果的正确性。 18.字符常量:由单引号括起来的字符如?a?、?K?、??? 等,还有另外一种字符常量称为转义字符就是以“\”开 头的字符序列。它是将字符转换成另外的意思,常见 转义字符及其含义在教材 P48 页表 3、3 列出一部分, 需要更多转义字符的表示和含义还需去查系统手册。 例如反斜杆 T 就是水平移 8 列,就是光标在第 9 列显 示;反斜杆 R 就是回车不换行;反斜杆 N 我们在前面 程序中经常用,就是把光标移到下一行开头显示;反 斜杆 1 到 3 位八进制数是表示八进制代表的字符;还 有一些就不一一在此讲解了,同学们自己回去看,这 里列出的一部分是我们比较经常用的转义字符。下面 我们举两个例子说明。19.例 1 输出人民币单位,输出大写字符 Y,然后执行 转义字符反斜杆 B,意思是光标退一格,正好退到大 写字符 Y 的位置上,再输出两横,然后再执行换行转 义字符,这时运行结果就是输出人民币单位。我们再 看看第二个例子, 输出大于等于号, 定义字符变量 CH, 给字符变量赋转义字符反斜杆 3 位八进制数, 362ASCII 码代表的字符是大于等于符号,因此让 CH 变量值按字符类型输出,其运行结果为这样。20.字符变量其定义形式为: char 变量名称,这在前面 例题中我们已经有用到。要强调几点的是 第一, 一个字符变量占内存一个字节, 因此一个 变量只能存放一个字符。第二,字符是以其 ASCII 代 码存到内存的,因此字符型数据和整型数据之间可以 通用。ASCII 代码是八进制数,它在内存中存放形式 与整型数据是一样的,因此它与整型数据是可以通用 的。如果内存中的数据以字符形式输出:ASCII 码转 换成字符再输出。整数形式输出:将 ASCII 码作为整 数直接输出。6 字符数据参加算术运算时, 相当于对其 ASCII 码进行算术运算, 运算前将 1 个字节转换为 2 个字 节。代表字符的这个字节放在低八位,高八位自动 补 0 或补 1,如果是无符号字符型就自动补 0,如 果是有符号字符型就视符号位是 0 还是 1,这叫符 号扩展。关于类型转换部分同学们可以自己看书。 现在举两个例子来说明字符变量的应用。 大家看这 个程序,定义了两个字符变量 C1 和 C2,给两个 字符型变量分别赋值,C1 赋给一个整型常量 97, C2 赋给一个字符 B,在显示器上输出,一个是两 个字符变量都以字符型输出, 另外一个都以十进制 整型输出,大家看看运行结果,以字符型输出的, 输出的就是字符,以十进制整型输出的它就是整 型。这说明字符型与整型之间可以通用。我们再举个例子,大小写字母的转换。我们看 看程序,首先定义两个字符型变量 C1 和 C2,并 给它赋初值,分别是字符 A 和 B,大家看看后面 两个运算语句, 直接把字符型变量与整型常量进行 运算,其结果是如何呢?好,大家看,运行结果为 输出两个大写字母 A 和 B,这是为什么?可以说 明两个问题,第一,字符变量参加算术运算是以其 ASCII 代码进行,大家可以看看附录 1,小写字母 A、B 的 ASCII 代码是多少,大家翻到 374 页,A、 B 的 ASCII 代码分别是 97 和 98, 那么它们分别减 32 后,等于 65 和 66,那么 65 和 66 分别又代表什 么字符呢?大家看看,对,代表的是大写字母 A 和 B,因此,我们把它们以字符型格式输出,小写 字母就转换成大写字母了。 语言对字符数据作这 C 种处理使程序设计时增加了自由度, 例如对字符作 各种转换就比较方便。对字符型变量还几点要说明的。说明:字符变 量中的最高位作为符号位,其 取值范围: -128~+127。若用%d 输出 ?ASCII 码为 0~127 间的字符,由于它符号位为 0 因此它输出一个正整数。 ? 若 ASCII 码为 128~255 时,它的符号位为 1, 因此得到一个负整数。 ? 若将字符变量定义为 unsigned char 型,此时取 值范围为 0~255。它们如果以整型格式输出的话, 它们都是 0 至 255 之间的正整数。7 第三点我们讲讲字符串常量,字符串常量与字 符常量有什么区别呢?规定字符串常量是一对双引 号括起来的字符序列。例如“How do you do.” , “”等等,这里要特别注意的是:不能用字 符串常量向字符变量赋值。如: char c ; /* 定义字符变量 */ c=?a?;这是把一个字符常量赋给字符变量, c= “a”;而这是把一个字符串赋串常量赋给字符 变量,这是不行的!为什么呢?按规定系统是这么 默认存储的,字符串常量后系统给自动加一个结束 字符反斜杆 0, 因此, 当把字符串 A 赋值给字符变量 C 时,系统自动在 A 字符后加一个字符结束字符, 那么赋给字符变量 C 就是两个字符, 因此出现错误, 那么字符串变量应该如何定义呢?这在后面我们会 讲到,用字符数组类型就可以赋值字符串。 第六节变量赋值 C 规定,可以在定义变量时对 变量进行初始化。方法为:变量=表达式把表达式的 值赋给变量,例如:float f=3.56;相当于:先定义变 量 f 为实型, 然后再赋值, 3.56 赋给 f, 把 再例如 char c=?a?;这个也相当于:先定义变量 C 为字符型,然 后再把 ?a?字符赋给变量 C,再例如我们也可以在定 义几个变量的同时,对部分变量进行赋初值,看看 这个例子就是这种情况,int a,b,c=5;相当于:对变 量 a,b,c 定义为 int,然后对 c=5 进行了赋值;还要 注意的几种方法,如果对几个变量赋同一个初值可 以用这两种方法,赋值语句是右结合性语句,因此 这条语句是先把 5 赋值给变量 C,然后再 C 变量值 赋给 B 变量,再把变量 B 的值赋给 A 变量,但是大 家要注意的是 a,b,c 只是有相同的初值,这并代表这 几个变量值永远相等,它们在执行过程中是可以改 变变量值的。这两条赋值语句是相同的意义。变量赋值我们就讲这么多,只要大家知道怎么 用就行了。现在我们讲讲第七节不同类型数据的混 合运算,大家看这个表格,它代表什么意思呢?现 在为止我们学了这几种类型的数据,有双精度型、 单精度型、长整型、无符号型、整型、字符型和短 整型,当它在一起进行混合运算时,是遵循什么样 的规则呢?这两个水平箭头代表在运算过程中是必 定转换的,无论运算式子中是否有其它类型存在, 单精度型必定转换成双精度型进行运算,字符型和 短整型必定转换成整型进行运算,然后再看这运算 式子中有没有其它类型,然后按照这种规则由低向 高进行转换,但并不等于说必须这么一级一级进行 转换,而是遇到什么样的类型,谁在高处就向谁转 换。例如整型与双精度型数据进行运算,那么直接 8 把整型转换成双精度型进行运算。我们举个例子进 行说明。 定义字符型变量 CH,定义整型变量 I 和 RESULT,定 义单精度型变量 F,定义双精型变量 D,现在把一个表达式 赋值给 RESULT,我们先进行表达式运算,有小括符先求括 符里的值,F 单精度型在运算过程中自动转换成 DOUBLE 型进行运算,当然 I 为整型,它与 DOUBLE 型进行加法运 算, 它必须转成 DOUBLE 型进行运算, 运算结果为 DOUBLE 型,然后我们求这整除运算,先要把字符型转换成整型进行 运算,运算结果为整型;接下来求 F 乘以 D,F 为单精度型, D 为双精度型, 因此先把 F 转换成双精度型然后再进行运算, 运算结果为双精度型,接下来自左向右求加法运算,当然整 型与 DOUBLE 型运算结果为 DOUBLE 型,DOUBLE 型与 DOUBLE 型相减当然是 DOUBLE 型。这时表达式运算完, 就要把运算结果赋值给整型变量 RESULT,这在后面要讲 到,双精度型数据要赋值给整型,采取舍弃的方法,把小数 部分舍弃赋值给变量 RESULT。接下来我们讲讲运算符与表达式,C 语言中,把几乎所 有的基本操作都作为运算符来处理,它的运算符非常丰富, 大家看看9 10 11 12 13 14C语言常量以及变量类型,存储类型和作用域
常量 : 在程序运行时,不会被修改的量。 常量区分为不同的类型,如25、0、-8为整形常量,6.8、-7.89为,&a&&b&为。 常量一般从其字面形式即可判断。这种常量称为字面常量或直接常量。 变量类型:
其值可以改变的量称为变量。一个变量应该有一个名字,在内存中占据一定的存储单元。变量定义必须放在变量使用之前。一般放在函数体的开头部分。要区分变量名和变量值是两个不同的概念。
变量定义的一般形式为:
类型说明符 变量名, 变量名, ...;
在书写变量定义时,应注意以下几点:
允许在一个类型说明符后,定义多个相同类型的变量。各变量名之间用逗号间隔。类型说明符与变量名之间至少用一个空格间隔。最后一个变量名之后必须以&;&号结尾。变量定义必须放在变量使用之前。一般放在函数体的开头部分。
变量定义举例:
变量的赋值
变量可以先定义再赋值,也可以在定义的同时进行赋值;在定义变量的同时赋初值称为初始化。
在变量定义中赋初值的一般形式为:
类型说明符 变量1= 值1, 变量2= 值2, &&;
注意,在定义中不允许连续赋值,如a=b=c=5是不合法的。
定义在函数内部的变量称为局部变量(Local Variable),它的作用域仅限于函数内部, 离开该函数后就是无效的,再使用就会报错。例如:
几点说明:
1) 在 main 函数中定义的变量也是局部变量,只能在 main 函数中使用;同时,main 函数中也不能使用其它函数中定义的变量。main 函数也是一个函数,与其它函数地位平等。
2) 形参变量、在函数体内定义的变量都是局部变量。实参给形参传值的过程也就是给局部变量赋值的过程。
3) 可以在不同的函数中使用相同的变量名,它们表示不同的数据,分配不同的内存,互不干扰,也不会发生混淆。
4) 在语句块中也可定义变量,它的作用域只限于当前语句块。
在所有函数外部定义的变量称为全局变量(Global Variable),它的作用域默认是整个程序,也就是所有的源文件,包括 .c 和 .h 文件。例如:
a、b、x、y 都是在函数外部定义的全局变量。C语言代码是从前往后依次执行的,由于 x、y 定义在函数 func1() 之后,所以在 func1() 内无效;而 a、b 定义在源程序的开头,所以在 func1()、func2() 和 main() 内都有效。
局部变量和全局变量的综合示例
【示例1】输出变量的值:
运行结果:
func1 n: 20
func2 n: 30
func3 n: 10
block n: 40
main n: 30
代码中虽然定义了多个同名变量 n,但它们的作用域不同,在内存中的位置(地址)也不同,所以是相互独立的变量,互不影响,不会产生重复定义(Redefinition)错误。
1) 对于 func1(),输出结果为 20,显然使用的是函数内部的 n,而不是外部的 n;func2() 也是相同的情况。
当全局变量和局部变量同名时,在局部范围内全局变量被&屏蔽&,不再起作用。或者说,变量的使用遵循就近原则,如果在当前作用域中存在同名变量,就不会向更大的作用域中去寻找变量。
2) func3() 输出 10,使用的是全局变量,因为在 func3() 函数中不存在局部变量 n,所以编译器只能到函数外部,也就是全局作用域中去寻找变量 n。
3) 由{ }包围的代码块也拥有独立的作用域,printf() 使用它自己内部的变量 n,输出 40。
3) C语言规定,只能从小的作用域向大的作用域中去寻找变量,而不能反过来,使用更小的作用域中的变量。对于 main() 函数,即使代码块中的 n 离输出语句更近,但它仍然会使用 main() 函数开头定义的 n,所以输出结果是 30。
============================================================================================ 举个例子, 我们家房顶上有一盏灯,名字叫做&小太阳&, 它什么时候亮什么时候熄灭,只有在我家这个房间才知道,宇航局在天上发射了一个发光装置,也起名叫做&小太阳&,它什么时候亮什么时候熄灭,只有在我出了家门才知道. 只有在我家里,大家提起&小太阳&这个名字,都是指的是我家的灯,而在外边大街上,大家提起&小太阳&这个名字,都指的是 宇航局的发光装置,而不会是我们家的灯. 在这里我家的房间就是函数内部, 而我家的小太阳是局部变量,而外边的小太阳是 全局变量.
static翻译出来是&静态&&静止&的意思,在C语言中的意思其实和它的本意差不多,表示&静态&或者&全局&的意思,用来修饰变量和函数。经static修饰过后的变量或者函数的作用域或者存储域会发生变化,而由static修饰的变量在初始值方面也会表现出static关键字的优势。想知道经static修饰过后的变量或者函数的作用域或者存储域发生了什么变化吗,发生变化的原因是什么吗?请大家继续往下看!
一、c程序的内存分布
既然static是用来修饰变量和函数的,而变量和函数又是组成c程序必不可少的,C程序的内存分布图如下。
  C程序由下面5部分组成:
  1)正文段&&CPU执行的机器指令部分;一个程序只有一个副本;只读,防止程序由于意外事故而修改自身指令;
  2)初始化数据段(数据段)&&在程序中所有赋了初值的全局变量,存放在这里。
  3)非初始化数据段(bss段)&&在程序中没有初始化的全局变量;内核将此段初始化为0。
4)栈&&增长方向:自顶向下增长;自动变量以及每次函数调用时所需要保存的信息(返回地址;环境信息)。
  5)堆&&动态存储区。是向高地址扩展的数据类型,是自下向上的扩展方式。
c程序内存分布图
上面的C程序分布图很明显的告诉我们,变量是存储在栈区或者堆区或者bss段或者data段,变量的存储域为什么会有所不同呢?其实原因很简单,说白了就是与他们定义在程序的不同地方,有没有static关键字修饰有关啦,定义在不同的地方也说明了他们有着不同的作用域。
二、static修饰的变量
1.全局静态变量
  在全局变量之前加上关键字static,全局变量就被定义成为一个全局静态变量。
  1)内存中的位置:静态存储区(静态存储区在整个程序运行期间都存在)
  2)初始化:未经初始化的全局静态变量会被程序自动初始化为0(自动对象的值是任意的,除非他被显示初始化)
  3)作用域:全局静态变量在声明他的文件之外是不可见的。准确地讲从定义之处开始到文件结尾。
  定义全局静态变量的好处:
  &1&不会被其他文件所访问,修改
  &2&其他文件中可以使用相同名字的变量,不会发生冲突。
  2.局部静态变量
在局部变量之前加上关键字static,局部变量就被定义成为一个局部静态变量。
  1)内存中的位置:静态存储区
  2)初始化:未经初始化的局部静态变量会被程序自动初始化为0(自动对象的值是任意的,除非他被显示初始化)
  3)作用域:作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域随之结束。
  注:当static用来修饰局部变量的时候,它就改变了局部变量的存储位置,从原来的栈中存放改为静态存储区。但是局部静态变量在离开作用域之后,并没有被销毁,而是仍然驻留在内存当中,直到程序结束,只不过我们不能再对他进行访问。
  当static用来修饰全局变量的时候,它就改变了全局变量的作用域(在声明他的文件之外是不可见的),但是没有改变它的存放位置,还是在静态存储区中。
三、Static修饰的函数
 在函数的返回类型前加上关键字static,函数就被定义成为静态函数。
函数的定义和声明默认情况下是extern的,但静态函数只是在声明他的文件中可见,不能被其他文件所用。
 定义静态函数的好处:
  &1&其他文件中可以定义相同名字的函数,不会发生冲突
&2&静态函数不能被其他文件所用。
存储说明符auto,register,extern,static,对应两种存储期:自动存储期和静态存储期。
  auto和register对应自动存储期。具有自动存储期的变量在进入声明该变量的程序块时被建立,它在该程序块活动时存在,退出该程序块时撤销。
  关键字extern和static用来说明具有静态存储期的变量和函数。用static声明的局部变量具有静态存储持续期(staticstorageduration),或静态范围(staticextent)。虽然他的值在函数调用之间保持有效,但是其名字的可视性仍限制在其局部域内。静态局部对象在程序执行到该对象的声明处时被首次初始化。
(1)第一个作用:隐藏。
当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。为理解这句话,我举例来说明。我们要同时编译两个源文件,一个是a.c,另一个是main.c。
下面是a.c的内容
#include增加这条语句
chara=&A&;//globalvariable
printf(&Hello\n&);
下面是main.c的内容
intmain(void)
//externvariablemustbedeclaredbeforeuse
printf(&%c&,a);
(void)msg();
程序的运行结果是:AHello
你可能会问:为什么在a.c中定义的全局变量a和函数msg能在main.c中使用?前面说过,所有未加static前缀的全局变量和函数都具有全局可见性,其它的源文件也能访问。此例中,a是全局变量,msg是函数,并且都没有加static前缀,因此对于另外的源文件main.c是可见的。
如果加了static,就会对其它源文件隐藏。例如在a和msg的定义前加上static,main.c就看不到它们了。利用这一特性可以在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。Static可以用作函数和变量的前缀,对于函数来讲,static的作用仅限于隐藏,而对于变量,static还有下面两个作用。
(2)static的第二个作用是保持变量内容的持久。存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。共有两种变量存储在静态存储区:全局变量和static变量,只不过和全局变量比起来,static可以控制变量的可见范围,说到底static还是用来隐藏的。
(3)static的第三个作用是默认初始化为0。其实全局变量也具备这一属性,因为全局变量也存储在静态数据区。在静态数据区,内存中所有的字节默认值都是0x00,某些时候这一特点可以减少程序员的工作量。
最后对static的三条作用做一句话总结。首先static的最主要功能是隐藏,其次因为static变量存放在静态存储区,所以它具备持久性和默认值0。
下面是main.c的内容
除了头文件,需要声明函数:voidmsg();
intmain(void)
//externvariablemustbedeclaredbeforeuse
printf(&%c&,a);
(void)msg();
double price = 123.123;
char a = 'a',
int b,c=5;
float x=3.2,y=3.0,z=0.75;
char ch1='K',ch2='P';
int f1(int a){
int b,c; //a,b,c仅在函数f1()内有效
return a+b+c;
int main(){
int m,n; //m,n仅在函数main()内有效
int a, //全局变量
void func1(){
float x,y; //全局变量
int func2(){
int main(){
int n = 10; //全局变量
void func1(){
int n = 20; //局部变量
printf(&func1 n: %d\n&, n);
void func2(int n){
printf(&func2 n: %d\n&, n);
void func3(){
printf(&func3 n: %d\n&, n);
int main(){
int n = 30; //局部变量
//代码块由{}包围
int n = 40; //局部变量
printf(&block n: %d\n&, n);
printf(&main n: %d\n&, n);

我要回帖

更多关于 java常量与变量 的文章

 

随机推荐