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
相关推荐
麻雀飞吧1 小时前
期货量化主连和具体合约怎么切:天勤 KQ.m 与 KQ.i 用法
python·区块链
先吃饱再说1 小时前
Python List 切片与 LLM Prompt 设计:从数据结构到接口调用
python
一只专注api接口开发的技术猿2 小时前
OpenClaw 对接淘宝商品 API,低成本实现全天候选品监控|附可运行 Python 实操代码
大数据·开发语言·数据库·python
xingpanvip2 小时前
星盘接口开发文档:马盘次限盘接口指南
android·开发语言·python·php·lua
FBI HackerHarry浩2 小时前
第二阶段Day07【Python生成器、yield关键字、property、正则表达式】
开发语言·python·正则表达式
梦想不只是梦与想2 小时前
Python 中的 4 种作用域
python·作用域
coderwei1232 小时前
从OpenAI到Strip:用六大支柱读懂Harness Engineering的生产实践
python·ai·ai编程
海鸥-w2 小时前
Python(FastAPI)中ORM框架Sqlalchemy的安装及建表
python
AI科技星3 小时前
基于光速螺旋第一性原理:$G,\varepsilon_0,\alpha$引电统一完整推导+严谨证明+高精度数值全维度分析
c语言·开发语言·网络·量子计算·agi