作用域和链接属性|学习笔记

简介: 当变量被定义在程序的不同位置时,它的作用范围是不一样的,这个作用范围就是我们所说的作用域。

开发者学堂课程【你的第一门 C 语言课作用域和链接属性】学习笔记,与课程紧密联系,让用户快速学习知识

课程地址:https://developer.aliyun.com/learning/course/444/detail/5480


作用域和链接属性


作用域

当变量被定义在程序的不同位置时,它的作用范围是不一样的,这作用范围就是我们所说的作用域。

C 语言编译器可以确认4种不同类型的作用域:

一代码块作用域

一文件作用域

一原型作用域

一函数作用域

1) 代码块作用域(block scope)

在代码块中定义的变量,具有代码块作用域。作用范围是从变量定义的位置开始,到标志该代码块结束的右大括号)处。

尽管函数的形式参数不在大括号内定义,但其同样具有代码块作用域,隶属于包含函数体的代码块。

include

int main(void)

{

int i = 100; //i1

{

int i = 110;//li

{

int i = 120;//i3

printf ( "i = %d\n", i);

}

//i =110

{

printf ( "i=%d\n", i);

int i = 130;

printf ( "i=%d\n", i);

}

printf ("i=%d \n", i);

}

printf("i= %d\n", i);

return 0;

}

2) 文件作用域(file scope)

任何在代码块之外声明的标识符都具有文件作用域,作用范围是从它们的声明位置开始,到文件的结尾处都是可以访问的。

另外,函数名也具有文件作用域,因为函数名本身也是在代码块之外。

#include

void func(void);

int main(void)

{

extern int count;

func();

count++;

printf( "In main, count = %d \n", count);

return 0;

}

int count;

void func(void)

{

count++;

printf( "In func, count = %d \n", count);

}

3) 原型作用域(prototype scope)

原型作用域只适用于那些在函数原型中声明的参数名。

例如:

图片95.png

函数在声明的时候可以不写参数的名字(但参数类型是必须要写上的),其实函数原型的参数名还可以随便写一个名字,不必与形式参数相匹配(当然,这样做没有任何意义!)。

4) 函数作用域(function scope)

函数作用域只适用于 goto 语句的标签,作用将 goto 语句的标签暖制在同一个函数内部,以及防止出现重名标签。

  • 定义和声明

当一个变量被定义的时候,编译器为变量申请内存空间并填充一些值。

当一个变量被声明的时候,编译器就知道该变量被定义在其他地方。

声明是通知编译器该变量名及相关的类型已存在,不需要再为此申请内存空间。

局部变量既是定义又是声明。

定义只能来一次,否则就叫做重复定义某个同名变量;而声明可以有很多次。

  • 链接属性

图片96.png

external(外部的)

一多个文件中声明的同名标识符表示同一个实体

internal(内部的)

一单个文件中声明的同名标识符表示同一个实体

none(无)

一声明的同名标识符被当作独立不同的实体

只有具备文件作用域的标识符才能拥有 externa l或 internal 的链接属性,其他作用域的标识符都是 none 属性。

默认情况下,具备文件作用域的标识符拥有 external 属性。也就是说该标识符允许跨文件访问。对于 external 属性的标识符,无论在不同文件中声明多少次,表示的都是同一个实体。

#include

void a(void) ;

void b(void);

void c(void);

int count;

int main(void)

{

a();

b();

c();

b();

printf("小郭今天一共被抱了%d次\n", count);

return 0;

}

  • 全局变量

extern int count;

void b (void)

{

count++;

}

使用 static 关键字可以使得原先拥有 external 属性的标识符变为 internal 属性。

这里有两点需要注意:

使用 static 关键字修改链接属性,只对具有文件

作用域的标识符生效(对于拥有其他作用域的标识符是另一种功能)

一链接属性只能修改一次,也就是说一旦将标识符的链接属性变为 internal,就无法变回 external 了

相关文章
|
数据采集 监控 大数据
大数据时代的数据质量与数据治理策略
在大数据时代,高质量数据对驱动企业决策和创新至关重要。然而,数据量的爆炸式增长带来了数据质量挑战,如准确性、完整性和时效性问题。本文探讨了数据质量的定义、重要性及评估方法,并提出数据治理策略,包括建立治理体系、数据质量管理流程和生命周期管理。通过使用Apache Nifi等工具进行数据质量监控和问题修复,结合元数据管理和数据集成工具,企业可以提升数据质量,释放数据价值。数据治理需要全员参与和持续优化,以应对数据质量挑战并推动企业发展。
3141 3
|
机器学习/深度学习 人工智能 Cloud Native
秒速出图!体验 TensorRT 加速 Stable Diffusion 图像创作
秒速出图!体验 TensorRT 加速 Stable Diffusion 图像创作
141381 116
|
存储 C语言
C语言版数据结构详解与实现
C语言版数据结构详解与实现
|
安全 Android开发
【Android 逆向】Android 中常用的 so 动态库 ( libm.so 数学函数动态库 | liblog.so 日志模块动态库 | libselinux.so 安全模块动态库 )
【Android 逆向】Android 中常用的 so 动态库 ( libm.so 数学函数动态库 | liblog.so 日志模块动态库 | libselinux.so 安全模块动态库 )
910 0
【Android 逆向】Android 中常用的 so 动态库 ( libm.so 数学函数动态库 | liblog.so 日志模块动态库 | libselinux.so 安全模块动态库 )
|
安全 网络安全 数据安全/隐私保护
Termius 一款优秀的跨平台 SSH 客户端工具
Termius 一款优秀的跨平台 SSH 客户端工具
1092 0
C# | 使用AutoResetEvent和ManualResetEvent进行线程同步和通信
在多线程编程中,AutoResetEvent 和 ManualResetEvent 是两个常用的同步原语。它们用于线程间的通信和协调,以确保线程按照特定的顺序执行。本篇博客将介绍这两种同步原语的概念、用法和区别。
340 0
C# | 使用AutoResetEvent和ManualResetEvent进行线程同步和通信
|
算法
labview信号时域分析编程笔记
labview信号时域分析编程笔记
366 0
|
IDE 编译器 Linux
VScode 编译器配置IDE环境(C/C++/Go)
VScode 编译器配置IDE环境(C/C++/Go)
1437 0
VScode 编译器配置IDE环境(C/C++/Go)
|
自然语言处理 算法 NoSQL
【六、深度解析Makefile】工程文件编译链接的“规则制定者”:带你走进 makefile 的世界(二)
【六、深度解析Makefile】工程文件编译链接的“规则制定者”:带你走进 makefile 的世界
411 0
【六、深度解析Makefile】工程文件编译链接的“规则制定者”:带你走进 makefile 的世界(二)