C语言,变量类型、生命周期和存储

本文详细探讨了不同类型的存储类型(静态、自动、动态和指针),它们的生命周期、内存分配和初始化方式,以及全局变量、局部变量和常量的特性。同时揭示了编程中声明、定义和内存分配的区别,对初学者理解和实践IT技术很有帮助。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

变量

1 存储类型和生命周期

1.1 静态类型,static,static

定义 = 声明 + 自动分配内存 + 手动初始化

static type var = val;
static type var = val s;
static type var1 = val1, var2 = val2;

定义 = 声明 + 自动分配内存 + 手动初始化

static type var;
static type vars;
static type var1, var2;
var = val;
var = val s;
var1 = val1, var2 = val2;

定义 = 声明 + 自动分配内存 + 自动初始化

static type var;
static type vars;
static type var1, var2;

赋值

var=val;
var = val s;
var1 = val1, var2 = val2;

调用

var;
vars;
var1, var2;

自动释放内存

1.2 自动类型,automatic,auto

定义 = 声明 + 自动分配内存 + 手动初始化

type var = val;
type var = val s;
type var1 = val1, var2 = val2;

定义 = 声明 + 自动分配内存 + 手动初始化

type var;
type vars;
type var1, var2;
var = val;
var = val s;
var1 = val1, var2 = val2;

声明,外部声明,真声明

extern type var;
extern type vars;
extern type var1, var2;

赋值

var=val;
var = val s;
var1 = val1, var2 = val2;

调用

var;
vars;
var1, var2;

自动释放内存

1.3 动态类型,dynamic,指针类型,*,alloc

定义 = 声明 + 手动分配内存 + 手动初始化

type *ptr = (type *)malloc(sizeof(type));
type *ptr = (type *)malloc(sizeof(type)) s;
type *ptr1 = (type *)malloc(sizeof(type)), *ptr2 = (type *)malloc(sizeof(type));
*ptr = val;
*ptr = val s;
*ptr1 = val1, *ptr2 = val2;

定义 = 声明 + 手动分配内存 + 手动初始化

type *ptr;
type *ptr s;
type *ptr1, *ptr2;
ptr = (type *)malloc(sizeof(type));
ptr = (type *)malloc(sizeof(type)) s;
ptr1 = (type *)malloc(sizeof(type)), ptr2 = (type *)malloc(sizeof(type));
*ptr = val;
*ptr = val s;
*ptr1 = val1, *ptr2 = val2;

赋值

*ptr = val;
*ptr = val s;
*ptr1 = val1, *ptr2 = val2;

调用

*ptr;
*ptr;
*ptr1, *ptr2;

手动释放内存

free(ptr);
free(ptr) s;
free(ptr1), free(ptr2);

2 存储类型和初始化次数

2.1 静态变量,static,static

  • 自动分配内存
  • 自动释放内存,data
  • 自动初始化,data
  • 手动初始化,data
  • 只初始化一次,初始化语句可以多次执行只有第一次生效
  • 可以多次赋值

类似于全局变量,但初始化在局部

不能用动态类型对静态类型进行初始化,因为静态变量在编译时分配内存,而动态类型在运行时才分配内存

2.2 自动变量,automatic,auto

  • 自动分配内存,stack
  • 自动释放内存
  • 手动初始化
  • 可以多次初始化,初始化语句可以多次执行多次生效
  • 可以多次赋值

2.3 动态变量,dynamic,指针变量,*,alloc

  • 手动分配内存,heap
  • 手动释放内存
  • 手动初始化
  • 可以多次初始化,初始化语句可以多次执行多次生效
  • 可以多次赋值

3 存储类型和内存管理

3.1 存储类型

  1. 局部自动变量、形参存储在栈区,位于高地址,向下增长
  2. 动态变量存储在堆区,位于低地址,向上增长
  3. 全局变量、静态变量存储在数据区中的全局(静态)区,位于高地址,向下增长
  4. 常量存储在数据区的常量区,位于高地址,向下增长
  5. 函数存储在代码区,位于低地址,向上增长

3.2 内存管理

  1. 栈区是由高地址到低地址向下增长
  2. 堆区是由低地址到高地址向上增长
  3. 数据区由高地址到低地址向下增长
  4. 代码区是从低地址到高地址向上增长

3.3 遇到的问题

问题:当在一个语句中定义多个变量时,右侧变量在低地址,左侧在高地址。

推断:优先定义最右边的变量,最后才定义最左边的。但这种理解是错误的

分析结果:在语句中定义的变量可能为自动类型,存储在栈区,地址向下增长,先定义左边的,再定义右边的

4 范围类型

全局变量和局部变量不会起冲突,优先使用局部的

4.1 全局变量,global

4.1.1 静态全局变量
  • 自动分配内存,data
  • 自动释放内存
  • 自动初始化,data
  • 手动初始化,data

只有定义时才能手动初始化

4.1.2 自动全局变量
  • 自动分配内存
  • 自动释放内存
  • 自动初始化,bss
  • 手动初始化,data

只有定义时才能手动初始化

4.1.3 动态全局变量
  • 手动分配内存,heap
  • 手动释放内存
  • 手动初始化

4.2 局部变量,local

4.2.1 静态局部变量
  • 自动分配内存,data
  • 自动释放内存
  • 自动初始化,data
  • 手动初始化,data
4.2.2 自动局部变量
  • 自动分配内存,stack
  • 自动释放内存
  • 手动初始化
4.2.3 动态局部变量
  • 手动分配内存,heap
  • 手动释放内存
  • 手动初始化

5 赋值类型、常量和变量

5.1 常量,constant,const,终值,final,final

只能初始化,不能赋值,const

5.1.1 静态常量、类常量、const

在类定义时只初始化一次,不可赋值,初始化语句只能执行一次。

类似于全局常量,但初始化在局部。

5.1.2 动态常量、对象常量、readonly

在类实例化、新建对象时只初始化一次,不可赋值,初始化语句只能执行一次。

在静态终值变量和动态终值变量不一样,一个是类常量,一个是对象常量

5.2 变量,variable,var

可以初始化,可以赋值,var

6 定义、声明、分配内存和初始化的概念辨析

6.1 定义 = 声明 + 分配内存 + 初始化

定义包括了声明,定义后无需声明,定义起到了声明的作用,但要注意作用域

变量的定义可以起到声明的作用

6.2 声明

宣称要用此变量,告诉编译器要用这个变量,在引用之前一定要有声明,变量定义后有作用域,变量的作用域之外要用外部声明extern

6.2.1 外部声明

用来告诉编译器有这个变量需要用到,但没有分配内存,包括在文件中暂时没定义或定义在其它文件

类比java、python中的导入import,或者类比函数外部声明

6.3 分配内存

自动变量和静态变量声明后自动分配内存

只分配内存而不初始化

从编程和逻辑的角度讲一定是先声明了,才能分配内存,不算定义,因为定义需要初始化,未初始化的变量的值是不确定的,是它原来内存里面一个值

从内存和物理的角度讲算定义了,不算声明,因为声明不要求分配内存,但这个变量已经分配了内存,就是可以用的,可以用就是定义了。

6.4 初始化

全局变量和静态变量自动初始化,局部变量、动态变量和自动变量不会
是变量的第一次赋值
需要先声明或者分配内存后才能初始化,不然调用了未声明或未定义的变量

### C语言变量生命周期可见性范围 #### 1. 变量生命周期 在C语言中,变量生命周期是指从变量被创建到其被销毁的时间段。不同类型的变量具有不同的生命周期,这取决于它们存储的位置及其声明方式。 - **自动变量** 自动变量通常是在函数内部或复合语句中定义的局部变量。这类变量存放在栈中,在进入其作用域时被创建,离开作用域时被销毁[^2]。例如: ```c void exampleFunction() { int autoVar = 10; // 自动变量 } ``` 当`exampleFunction()`结束执行时,`autoVar`会被销毁。 - **静态变量** 静态变量可以是局部静态变量或全局静态变量。无论在哪种情况下,静态变量都在程序启动时初始化,并在整个程序运行期间保持存在[^3]。例如: ```c void staticExample() { static int count = 0; // 局部静态变量 count++; printf("%d\n", count); } ``` 每次调用`staticExample()`时,`count`不会重新初始化而是保留上次的值。 - **动态分配变量** 动态分配的变量通过`malloc`、`calloc`等函数申请堆内存空间。这些变量的生命期由程序员显式控制,只有在其对应的内存被释放(如使用`free`)之后才会终止生命期[^4]。例如: ```c int *dynamicVar = (int *)malloc(sizeof(int)); if (dynamicVar != NULL) { *dynamicVar = 20; } // 使用完成后需手动释放 free(dynamicVar); ``` --- #### 2. 变量的可见性范围与作用域 变量的可见性范围与其作用域密切相关,具体分为以下几个方面: - **局部作用域** 定义于某个特定代码块内的变量仅在此代码块内有效。一旦超出此代码块,则无法访问该变量[^1]。例如: ```c { int localVar = 5; // 局部变量 printf("%d\n", localVar); // 正确 } printf("%d\n", localVar); // 错误:localVar不可见 ``` - **文件作用域(外部变量)** 外部变量也称为全局变量,定义在任何函数之外。此类变量可以在整个源文件范围内访问,除非另有修饰符限制其可见性[^3]。例如: ```c int globalVar = 10; void functionA() { printf("%d\n", globalVar); // 访问成功 } void functionB() { printf("%d\n", globalVar); // 同样可以访问 } ``` - **静态作用域** 当前文件中的静态变量只能被当前文件中的其他部分访问,即使其他文件包含了相同的名称也无法直接共享。例如: ```c static int fileStaticVar = 20; void accessFileStatic() { printf("%d\n", fileStaticVar); // 成功 } ``` 另一个文件尝试访问`fileStaticVar`将会失败。 - **形式参数与返回值的作用域** 函数的形式参数属于局部作用域的一部分,仅在函数体内可用;而函数返回值则传递给调用者后即失去关联[^1]。 --- ### 总结 综上所述,C语言变量生命周期主要受其存储位置影响,包括栈上的自动变量、数据区中的静态变量以及堆上的动态分配变量。与此同时,变量的可见性范围依据其作用域来决定,可能局限于单个代码块、整个文件或者跨多个文件的情况。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值