C_and_CPP 板


LINE

最近想把程式写的有系统一点, 就研究了一下变数储存等级(storage class) 想说把心得整理成笔记, 顺便分享给大家~ 下面讨论的主要以 C语言 为主 1. 区块 (block) 例如: { .... } 区块就是任何以大括号包起来的区域, 如函式区块, if区块, for区块 严格说起来, 在任何 statement 出现之前, 一定要把 block 内使用到的变数定义好 在 block 外定义的变数就是 global variable 在 block 内定义的变数就是 local variable 在 block 内想要使用不在 scope 里的 global variable, 就要用 extern 宣告此变数 在 block 外想要使用 local variable, 很可惜, C语言没有支援这种功能 在 block 内定义的变数, 会遮蔽 block 外定义的变数 2. 宣告 (declaration) 例如: (auto) int a; // in block, 定义 + 宣告 int a; // out block, 定义 + 宣告 extern int a; // out block, 宣告 宣告主要是告诉 compiler 说 "这个变数之前有定义过了, 我现在要用这个变数罗" 如果配合储存等级, 就是说 "此变数的 scope 和 lifetime 是如 keyword 所指定的" 如果变数使用前没有先宣告, 会有 undeclare 的错误 我觉得宣告最主要的作用就是把变数的 scope 和 lifetime 定出来 3. 定义 (definition) 例如: (auto) int a; // in block, 定义 + 宣告 int a; // out block, 定义 + 宣告 extern int a = 0; // out block, 定义 + 宣告 (其实 extern 是多余的) 定义就是 memory or stack 配一个空间给变数, 一个变数当然只能有一个空间 local auto variable 是在 run-time 的时候由 stack 配给空间, 初值是随机给的 其他的情况, 则是在程式开始执行的时候就占有 memory 的空间, 初值是0 local static variable 如 { static int a = 5; } 只会在第一次定义时给初值 之後再碰到此叙述时, 会将其视为宣告, 而不会再做初始化的动作 定义有宣告的效果, 但是宣告没有定义的效果 在同一个 scope 里面, 定义只能有一次, 宣告则可以有很多次 例外: int a; { int a; } 虽然第一个 int a; 的 scope 有触及到 block 里面 但是第二个 int a; 把第一个 int a; 的效果遮蔽掉了, 所以不能算定义两次 如果变数在同一个 scope 里定义两次以上, 会有 redefine 的错误 如果变数只有宣告而没有定义, 会有 undefine 的错误 4. 作用范围 (scope) 作用范围就是一个变数能触及到的视野, 在变数的 scope 里, 使用该变数都有效 每种 storage class 都有其自然视野(natural scope) 想要扩展变数的 scope, 就要使用 extern 宣告来增加其腹地 自然视野大致可分为 block scope, file scope 两种 block scope 就是从变数宣告开始, 到 block 结束为止 file scope 就是从变数宣告开始, 到 file 结束为止 会发生 undeclare 的错误, 就是因为没在某变数的 scope 里使用该变数 5. 生命期 (lifetime) 生命期就是一个变数生存的时间, 当变数的 lifetime 过了 则这个变数就完全无效了, memory 里的空间也就 free 掉了, 即使再宣告也没用 会发生 undefine 的错误, 就是因为没在某变数的 lifetime 里使用该变数 会发生 redefine 的错误, 就是因为两个同名的变数, 在同一时期生活在一起 这边同样要注意 block 的遮蔽效果, 可以让两个同名的变数生活在不同的世界 变数的生命期分两种 一种是 local auto variable, 其生命期是从 stack 配空间开始, 到 block 结束为止 其他的情况, 都是从程式执行开始, 到程式结束为止 6. 储存等级 (storage class) 储存等级的 keyword: auto, static, extern, register 这边不讨论 register, 因为现在的 compiler 有时候比人还强, 比人更了解底层机器 而 extern 主要只是搭配 global variable 去拓展 scope 而已 剩下的两个 keyword (auto, static), 再配上 block 的观念, 只剩四种可能 | | | in/out block | keyword | natural scope | lifetime | | | ======================================================================== | | | | (auto) int a; | block scope | to block end | | | local ---------------------------------------------------------- | | | | static int a; | block scope | whole program | | | ------------------------------------------------------------------------ | | | | int a; | file scope | whole program | | | global ---------------------------------------------------------- | | | | static int a; | file scope | whole program | | (strictly) | ------------------------------------------------------------------------ ※ static 在 local variable 的作用是改变 lifetime ※ static 在 global variable 的作用是影响 scope 扩展的限制 如果 global variable 没有加 static 修饰, 则可以用 extern 跨 file 宣告 如果 global variable 有使用 static 修饰, 则不能用 extern 跨 file 宣告 所以利用 static 可以做到变数封装的效果, 也就是 C++ class 的效果 ※ extern 只对 global variable 有作用而已 ※ 若在 block 内使用 extern, 则所增加的 scope 为 block scope 若在 block 外使用 extern, 则所增加的 scope 为 file scope 7. 函式 (function) 函式也是一个外在个体, 可以完全视为一个 global variable 以上所有适用於 global variable 的条例, 都适用於 function 8. 动态记忆体配置 (dynamic memory allocation) 动态记忆体配置一般是由 malloc 以及 free 这一对 C library function call 完成 最大的好处在於可以自由的指定配置时机, 以及自由的指定配置空间 动态记忆体配置只是一个经由 system call 向 OS 要记忆体的方式 所以它没有宣告和定义的行为, 当然也没有 lifetime 和 scope 的观念 因此配置的空间从 malloc 开始, 到 free 掉为止, 都存在着 只要有指标指向这个空间, 就可以去存取, 一次存取的大小以指标的 data type 决定 而释放记忆体空间时, 只要有指标指向这段空间的开头, 再用 free 即可 9. 编译 (compile) 编译的时候, 是一次 compile 一个 file, 就算再怎麽大的程式 compiler 一次也只看一个档案, 顶多先把一些 global variable 定义记起来 等到 link 阶段的时候, 看看会不会有 redefine or undefine 的情况 所以要写一个大程式, 只要注意几件事 (1) 整个 program 里面, 每个 global variable 都有定义, 而且只有定义一次 (2) 每个 file 里面, 任何一个变数在使用前, 都有先宣告过 (3) 使用 local auto variable 时, 要注意其 lifetime (4) 使用 extern 时, 该变数在别的地方要有定义 (5) 在 block 内可以利用 static 来增加 lifetime (6) 在 block 外可以利用 static 来封装资料 (7) 要注意 block 的遮蔽效果 (8) 在 .h 档里面, 要使用 ifndef, define 等条件式编译, 避免 redefine 的情况 大概就是这些重点罗, 如果有什麽地方的观念有错, 欢迎大家指正, 谢谢~ --



※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 140.112.29.206
1F:推 Skymaker:推,整理的不错 04/12 09:31
2F:→ neutronstars:推~ 04/12 10:30
3F:推 final01:那static function呢?有人写我无法体会用意~ 04/12 15:20
4F:推 wlsabcd:static function只能在同一个file里的function被呼叫 04/12 21:14
5F:推 asglay:有关scope的部分现在似乎都交给namespace去做而少用static 04/13 04:31
6F:推 ginobilidola:推 有很多很有用的观念~ 04/13 17:08
※ 编辑: shyang55 来自: 140.112.29.206 (04/16 03:04)
7F:推 wixter:推 借转XD 10/20 21:28
8F:推 uj2003:好文借转 04/12 09:49







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:e-shopping站内搜寻

TOP