C语言中的作用域、链接属性与存储属性
C语言中的作用域、链接属性与存储属性
一、作用域(scope)
代码块作用域
表示{}之间的区域,下例所示,a可以在不同的代码块里面定义。
#include<stdio.h> int main()
{
int f(int g){
return g;
} int a = 0;
{
int a = 2;
printf("inner: %d\n", a);
}
printf("outter: %d\n", a);
printf("inline function:%d\n", f(10));
}
$ ./a.out
inner: 2
outter: 0
inline function:10
C语言居然支持了内部函数,好神奇。
```c
//error: ‘i’ redeclared as different kind of symbol
int fun(int i)
{
int i = 0;
return i;
}
```
ANSI C中,形参的作用域为函数最外层的那个作用域,不能在函数体内声明同名的变量(K&R C可以,屏蔽形参)。
文件作用域
任何在所有代码块之外声明的标识符都具有文件作用域(file scope)。并且,通过#include指令包含到其他文件中的声明就好像它们是直接写在那些文件中一样。它们的作用域并不局限于头文件的文件尾。
原型作用域
int fun(int a);
原型作用域(prototype scope)只适用于在函数原型中声明的参数名,将它独立出来只是为了这个名字不能与其他作用域的符号混淆,它其实没有什么用得,甚至都可以不写。事实上,唯一可能出现的冲突就是在同一个原型中不止一次使用同一个名字。
函数作用域
它只适用于语句标签,用于goto语句。《C和指针》的作者说愿你永远不需要这方面的知识,哈哈!!!
二、链接属性
当组成一个程序的各个源文件分别被编译之后,所有的目标文件以及那些从一个或多个函数库中引用的函数链接在一起,形成可执行文件。问题是,如果相同的标识符出现在几个不同的源文件中时该怎么办?标识符的链接属性决定如何处理在不同文件中出现的标识符。标识符的作用域与它的链接属性有关,但这两者并不相同。
链接属性一共有3种:
none(无)
总是被当做单独的个体,也就是说该标识符的多个声明被当作独立不同的实体。
internal(内部)
在同一个源文件中的所有声明中都指向同一个实体,但位于不同源文件的多个声明则分属不同的实体。
external(外部):
不论声明多少次、位于几个源文件都表示同一个实体。
extern和static两个关键字可以用于设定标识符的链接属性。当没有这两个关键字时,默认的链接属性与标识符的作用域相关。
typedef char *a;
int b;
int c(int d)
{
int e;
int f(int g);
...
}
上面的代码块中,b、c、f有external链接属性,f在本代码中被调用,定义在其他源文件或者库中,所以也是external属性。其他的标识符都是none属性。
static关键字可以把一个默认为external属性的标识符改为internal,如上例中,可以把b、c的链接属性改为internal,使其在其他源文件中不可见。
static int b;
static int c(int d);
extern 关键中可以把none属性改为external属性。
// linkage_test1.c
#include<stdio.h> extern int a; // 可选,因为默认就是external
// 但是应该写上,增加程序可读性 int main() {
printf("a = %d\n", a);
extern int b; // 必需,默认为none
printf("b = %d\n", b);
}
// linkage_test1.c
int a = 1;
int b = 2;最后,当extern关键字用于源文件中一个标识符的一次声明时,它指定该标识符具有external链接属性,但是,如果它用于该标识符的第2次或者以后的声明时,它并不会更改由第一次声明所指定的链接属性。如下例所示:
static int i;
int func()
{
extern int i; //i的链接属性仍然为static
}
三、存储类型
变量的存储类型是指存储变量值的内存类型。变量的存储类型决定变量何时创建、何时销毁以及它的值将保持多久。有三个地方可以用于存储变量:普通内存、运行时堆栈、硬件寄存器。在这三个地方存储的变量具有不同的特性。
普通内存变量
变量的缺省存储类型取决于它声明的位置(作用域),凡是在任何代码块之外声明的变量总是存储与静态内存中,也就是不属于堆栈的内存,这类变量成为静态变量(static),可以通过static关键字将一个代码块内部变量由堆栈类型变为静态类型。静态类型的标识符存在ELF文件的.data(已初始化)或者.bss段(未初始化,默认值为0)。这些变量在程序未运行之前(通过内存加载)已经存在。
堆栈变量
在代码块内部声明的变量的默认存储类型是自动的(automatic),可以使用关键字auto指定,但它极少使用,因为完全没必要。这些自动变量存在堆栈中。
硬件寄存器变量
你可以通过关键字register来指定,提示程序运行时用硬件寄存器来存储该变量,但是编译器可以不鸟你,因为它认为它比你更清楚那个变量该用寄存器那个该用堆栈。
变量的初始化
静态变量只能用常数进行初始化(其他静态变量都不行),如果未显性初始化,则默认值为0;
堆栈变量可以通过任何合法表达式初始化,因为它是在运行时创建,如果不初始化,其默认值为垃圾。
引用
--C和指针/ (美)里科(Reek, K. A.)著;徐波译. —北京:人民邮电出版社,2008. 4(2016. 5重印)
C语言中的作用域、链接属性与存储属性的更多相关文章
- C语言中的作用域,链接属性和存储类型
作用域 当变量在程序的某个部分被声明的时候,他只有在程序的一定渔区才能被访问,编译器可以确认4种不同类型的作用域:文件作用域,函数作用域,代码块作用域和原型作用域 1.代码块作用域:位于一对花括号之间 ...
- C/C++语言中变量作用域:局部变量,全局变量,文件级变量
C/C++语言中的变量分为全局变量和局部变量. 这样的划分方式的根据是变量的可见范围或者叫做作用域. 1 局部变量 局部变量指的是定义在{}中的变量,其作用域也在这个范围内.尽管常见的局部变量都是定义 ...
- c语言中变量和函数作用域深究
首先,函数的作用域和访问权限基本可以参考 C语言中的作用域,链接属性和存储类型 也存在例外情况,比如内联函数 static inline,使用static 修饰 inline之后外部文件也可以访问内联 ...
- C语言 变量的作用域和生命周期(转)
转自 https://blog.csdn.net/u011616739/article/details/62052179 a.普通局部变量 属于某个{},在{}外部不能使用此变量,在{}内部是可以使用 ...
- 详解Go语言中的屏蔽现象
在刚开始学习Go语言的过程中,难免会遇到一些问题,尤其是从其他语言转向Go开发的人员,面对语法及其内部实现的差异,在使用Go开发时也避免不了会踩"坑".本文主要针对Go设计中的屏蔽 ...
- ruby中的作用域
作用域(scope)指的是变量的可达性或可见性.不同类型的变量有不同的作用域规则.与self类似,作用域在程序的执行过程中也在不断的变化,也可以根据上下文推断出"谁在什么作用域中" ...
- C语言中的传值调用
在c语言中每个变量都有两个属性一个是值,一个是址. 比方: int a = 2; 变量a的值是2,变量a的地址,能够用&取地址操作符获取,即&a. 因此以C语言的函数传递中具备两种方式 ...
- Swift编程语言学习9—— 存储属性和计算属性
属性将值跟特定的类.结构或枚举关联.存储属性存储常量或变量作为实例的一部分,计算属性计算(而不是存储)一个值.计算属性能够用于类.结构体和枚举里,存储属性仅仅能用于类和结构体. 存储属性和计算属性通经 ...
- 《从零开始学Swift》学习笔记(Day 31)——存储属性
原创文章,欢迎转载.转载请注明:关东升的博客 Swift中的属性分为存储属性和计算属性,存储属性就是Objective-C中的数据成员,计算属性不存储数据,但可以通过计算其他属性返回数据. 存储属性可 ...
随机推荐
- DB2数据库load出现SQL3508N问题
SQL3508N装入或装入查询期间,当存取类型为 "<文件类型>"的文件或路径时出错.原因码:"<原因码>".路径:"< ...
- 在应用层通过spring特性解决数据库读写分离
如何配置mysql数据库的主从? 单机配置mysql主从:http://my.oschina.net/god/blog/496 常见的解决数据库读写分离有两种方案 1.应用层 http://neore ...
- hdu 1532 Drainage Ditches 【ISAP 】
还是不是很懂算法 先存一个模板先吧--- 看的这篇学的-- http://www.renfei.org/blog/isap.html #include<cstdio> #include&l ...
- iOS 处理图片的一些小 Tip
UIImage 缓存是怎么回事? 通过 imageNamed 创建 UIImage 时,系统实际上只是在 Bundle 内查找到文件名,然后把这个文件名放到 UIImage 里返回,并没有进行实际的文 ...
- Vue学习之路第八篇:事件修饰符
学习准备: ①.顾名思义,“事件修饰符”那么肯定是用来修饰事件,既然和事件有关系,那么肯定和“v-on”指令(也可简写为:@)有关系了. ②.事件修饰符有以下几类: .stop:阻止冒泡 .preve ...
- mysql局域网服务搭建
首先配置电脑Mysql环境变量 新建 Mysql服务配置 CMD >命令 : mysql -u root -p 4. 创建用户 Mysql 用户权限分配 5 重启服务 如果还不能访问就一定是你的 ...
- 线性回归(regression)
简介 回归分析只涉及到两个变量的,称一元回归分析.一元回归的主要任务是从两个相关变量中的一个变量去估计另一个变量,被估计的变量,称因变量,可设为Y:估计出的变量,称自变量,设为X. 回归分析就是要找出 ...
- pytorch 8 CNN 卷积神经网络
# library # standard library import os # third-party library import torch import torch.nn as nn impo ...
- WampServer更改或重置数据库密码
WampServer安装后密码是空的, 修改一般有两种方式: 一是通过phpMyAdmin直接修改: 二是使用WAMP的MySql控制台修改. 第一种: ①在phpMyAdmin界面中点击[用户],将 ...
- tp框架,addAll方法报错,返回false
tp框架的批量添加addAll($data)方法很实用,但是注意,数据数组的数据结构要保持一致,不然会返回false.