C语言&Python&Bash&Tcl:全局变量和局部变量

C语言

在C语言中,变量根据定义位置的不同,可分为全局变量和局部变量。全局变量是指在函数外定义的变量,它的作用域通常从定义位置开始一直持续到源文件结束,生命周期贯穿整个程序运行期间。

复制代码
// 例1
#include <stdio.h>

int a = 100;

int main()
{
    printf("%d\n", a);
}

  例1中的变量a定义在函数外,因此属于全局变量。全局变量在程序启动时分配存储空间,在程序结束时释放,因此即使没有显式初始化,也会自动初始化为0,如例2所示。

复制代码
// 例2
#include <stdio.h>

int a;

int main()
{
    printf("%d\n", a);
}

输出:
0

全局变量可以在其他位置通过extern关键字进行声明,如例3所示。

复制代码
// 例3
#include <stdio.h>

int a = 111;

int main()
{
    extern int a;
    printf("%d\n", a);
}

输出:
111

extern关键字表示变量定义在其他位置,此处仅进行声明,不会重新分配存储空间。如果extern声明的变量不存在,则链接阶段会报错。

局部变量是指在函数体或代码块内部定义的变量,其作用域仅限于所在代码块。

复制代码
// 例4
#include <stdio.h>

int main()
{
    int a = 111;
    printf("%d\n", a);
}

例4中的变量a定义在main函数内部,因此属于局部变量。局部变量在进入代码块时创建,离开代码块时销毁,其生命周期通常与函数调用过程一致。与全局变量不同,局部变量若未初始化,其值是不确定的,如例5所示。

复制代码
// 例5
#include <stdio.h>

int main()
{
    int a;
    printf("%d\n", a);
}

例5能够通过编译,但输出结果未定义,编译器通常会给出警告。当局部变量与全局变量同名时,局部变量会遮蔽全局变量,如例6所示。

复制代码
// 例6
#include <stdio.h>

int a = 100;

int main()
{
    int a = 200;
    printf("%d\n", a);
}

输出:
200

例6中的局部变量a优先级更高,因此读取的是局部变量。如果全局变量使用static修饰,则其链接属性会变为内部链接(internal linkage),即只能在当前源文件访问。

复制代码
// a.c
static int a = 100;

// b.c
extern int a;

上述代码会导致链接失败,因为static全局变量不会导出到其他源文件。

Python

在Python中,变量根据作用域的不同,也可以分为全局变量和局部变量。通常情况下,在模块顶层定义的变量属于全局变量,其作用域为整个模块,如例7所示。

复制代码
# 例7
a = 100

print(a)

例7中的a定义在模块顶层,因此属于全局变量。函数内部可以直接读取全局变量,如例8所示。

复制代码
# 例8
a = 111

def func():
    print(a)

func()

输出:
111

虽然函数内部可以读取全局变量,但如果在函数内部对同名变量赋值,则默认会创建局部变量。

复制代码
# 例9
a = 111

def func():
    a = 222
    print(a)

func()
print(a)

输出:
222
111

例9中函数内部的a是局部变量,不会赋值全局变量。如果需要赋值全局变量,则需要使用global关键字。在Python中,如果函数内部既读取又赋值同名变量,则该变量会被整体视为局部变量,如例11所示。

复制代码
# 例11
a = 111

def func():
    print(a)
    a = 222

func()

输出:
UnboundLocalError:
local variable 'a' referenced before assignment

关于例11所示结果的进一步阐述,可以参考下面的博客。

Python:标识符的作用域解析https://chenzhang.blog.csdn.net/article/details/132156898

Bash

在Bash中,变量默认属于全局变量,如例13所示。

复制代码
# 例13
a=111

echo $a

输出:
111

例13中的a可以在整个Shell脚本中访问。在函数内部定义变量时,如果不使用local关键字,则该变量仍然是全局变量,如例14所示。

复制代码
# 例14
func()
{
    a=222
}

func
echo $a

输出:
222

例14中的a虽然定义在函数内部,但仍然赋值了全局变量。如果希望变量仅在函数内部有效,则需要使用local关键字,如例15所示。

复制代码
# 例15
a=111

func()
{
    local a=222
    echo $a
}

func
echo $a

输出:
222
111

例15中的local a语句创建了局部变量,因此不会影响全局变量。当local变量与全局变量同名时,局部变量会遮蔽全局变量,如例16所示。

复制代码
# 例16
a=111

func()
{
    local a=222
    echo $a
}

func
echo $a

输出:
222
111

Bash中不会出现类似Python中那种UnboundLocalError,如例17所示。原因在于,Python在函数定义时就会分析作用域(静态作用域、LEGB规则);而Bash在执行时才查找变量(动态查找)。

复制代码
# 例17
a=111

func()
{
    echo $a
    local a=222
}

func

输出:
111

Tcl

在Tcl中,变量默认根据所在位置决定作用域。在proc之外定义的变量属于全局变量,如例19所示。

复制代码
# 例19
set a 111
puts $a

输出:
111

例19中的a属于全局变量。在proc内部通过set创建的变量,默认属于局部变量,如例20所示。

复制代码
# 例20
proc func {} {
    set a 222
    puts $a
}

func

输出:
222

proc内部默认无法直接读取和赋值全局变量,如果需要访问全局变量,需要使用global命令(后续代码更简洁,适合频繁访问)或使用作用域解析符::(变量来源更明确,适合偶尔访问

)访问全局变量,如例21所示。

复制代码
# 例21
set a 111
set b 111
proc func {} {
    global a
    set a 222
    set ::b 222
}

func
puts $a
puts $b

输出:
222
222

需要注意的是,使用global命令要求变量在之前未定义,例22会报错。

复制代码
# 例21
set a 111
set b 111
proc func {} {
    set a 222
    global a    
    set ::b 222
}

func
puts $a
puts $b
相关推荐
学测绘的小杨6 小时前
CompassFusion:一个从 GNSS 到 GNSS/INS 组合导航的独立工程包
python
zzzzzz31013 小时前
当产品经理说这个很简单:我用Python自动化处理奇葩需求的实战指南
python·pycharm·产品经理
雪隐13 小时前
个人电脑玩AI-06让5060 Ti给你打工——不光能画画,Qwen3-TTS还能学人说话,连我老板都信了!
人工智能·后端·python
兵慌码乱1 天前
面向桌面端的资产管理系统分层架构设计与核心模块实现
python·系统架构·sqlite·pyqt5·数据库设计·桌面应用开发·mvc架构
hboot1 天前
AI工程师第三课 - 机器学习基础
python·scikit-learn·kaggle
顾林海1 天前
Agent入门阶段-编程基础-Python:流程控制
python·agent·ai编程
呱呱复呱呱1 天前
Django CBV 源码解读:一个请求是怎么找到你的 get() 方法的
python·django
曲幽2 天前
刚部署的 LibreTranslate 频频翻车?我掏出了 20 年前的 StarDict 词典,用 FastAPI 搭了个本地词典翻译 API
python·fastapi·web·translate·goldendict·libretranslate·stardict·pystardict
荣码2 天前
用Streamlit给AI应用套个界面,10行代码出Web页面
java·python
兵慌码乱2 天前
基于Python+PyQt5+SQLite的药房管理系统实现:事务一致性与界面解耦全流程解析
python·sqlite·信号与槽·pyqt5·数据库设计·桌面应用开发·事务处理