C语言存储类别和链接

目录

  • C语言存储类别和链接

    • 存储类别
    • 存储期
    • 五种存储类别

C语言存储类别和链接

? 最近详细的复习C语言,看到存储类别的时候总感觉一些概念模糊不清,现在认真的梳理一下。C语言的优势之一能够让程序员恰到好处的控制程序,可以通过C语言的内存管理系统指定变量的作用域和生存周期,实现对程序的控制。

存储类别

  • 基本概念

对象:在C语言中所有的数据都会被存储到内存中,被存储的值会占用一定的物理内存,这样的一块内存被称为对象,它可以储存一个或者多个值,在储存适当的值时一定具有相应的大小。(C语言对象不同于面向对象语言的对象)

标识符:程序需要一种方法来访问对象,这就需要声明变量来实现,例如: int identifier = 1,在这里identifier就是一个标识符,标识符是一个名称并遵循变量的命名规则。所以在本例中identifier即是C程序指定硬件内存中的对象的方式并提供了存储的值的大小“1”。在其它的情况中 int * ptint arr[10],pt就是一个标志符,它指定了储存地址的变量,但是表达式*p不是一个标志符,因为它不是一个名称。arr的声明创建了一个可容纳10个int类型元素的对象,该数组的每一个元素也是一个对象。

作用域:描述程序中可访问标识符的区域。因为一个C变量的作用域可以是块作用域、函数作用域、文件作用域和函数原型作用域。

块作用域:简单来说块作用域就是一对花括号括起来的代码区域。定义在块中的变量具有块作用域,范围是定义处到包含该定义块的末尾。

函数原型作用域:范围是从形参定义处到函数原型声明的结束。我们知道编译器在处理函数形参时只关心它的类型,而形参的名字通常无关紧要。例如:

void fun(int n,double m);     同样可以声明为

void fun(int ,double );

还有一点要注意的是函数体的形参虽然声明在函数的左花括号之前但是它具有的是块作用域属于函数体这个块。

文件作用域:变量的定义在所有函数的外面,从它的定义处到该文件的末尾处均可见称这个变量拥有文件作用域。所以文件作用域变量也被称为全局变量

链接:C变量有三种链接属性:内部链接、外部链接和无链接。具有块作用域、函数原型作用域的变量都是无链接变量,这就意味这他们属于定义他们的块或者函数原型私有。文件作用域变量可以是外部链接或是内部链接,外部链接可以在多个文件中使用,内部链接只能定义它的文件单元中使用。

存储期

指对象在内存中保留了多长时间,作用域和链接描述了对象的可见性。存储期则描述了标识符访问对象的生存期。

C对象有4种存储期:

1) 静态存储期:如果一个对象具有静态存储期,那么它在程序的执行期间一直存在。文件作用域变量具有静态存储期,注意关键字static表明的是链接属性而不是存储期。以static声明的文件作用域变量具有内部链接,无论具有内部链接还是外部链接,所有的文件作用域变量都具有静态存储期。

还有一种情况块作用域变量也可以拥有静态存储期,把变量声明在块中并在变量名前加static关键字,例:

int fun(int num)
{
    static int Index;
    ...
}

在这里变量Index就被存储在静态内存中,从程序被载入到程序结束都会存在,但是只有程序进入这个块中才会访问它指定的对象。

2) 线程存储期:用于并发程序设计,一个程序的执行可以分为多个线程,具有线程存储期的变量从被声明时到线程结束一直存在。以关键字_Thread_local声明一个对象时,每个线程都获得该变量的私有备份。

3) 自动存储期:块作用域变量通常具有自动存储期,当程序进入定义这些变量的块时,会为这些变量分配内存,当程序离开这个块时会自动释放变量占用的内存,这种做法相当于把自动变量占用的内存视为可重复利用的工作区或暂存区。

4) 动态分配存储期

五种存储类别

  • 五种存储类别
存储类别 存储期 作用域 链接 声明方式
自动 自动 无链接 块内
寄存器 自动 无链接 块内 关键字regsiter
静态外部链接 静态 文件 外部 所有函数外
静态内部链接 静态 文件 外部 所有函数外 关键字static
静态无链接 静态 块内 关键字static
  • 自动变量

自动变量属于自动识别的变量具有自动存储期,块作用域且无链接。可以显示的使用auto关键字进行声明。

注意: auto是存储类别说明符和C++中的auto用法完全不同

一个变量具有自动存储期就意味着当程序进入这个块时变量存在,退出块时变量消失,原来变量占用的内存另作他用。

void hiding()
{
    int x = 30;
    printf("x in outer block: %d at %p\n", x, &x);
    {
        x = 77;
        printf("x in inner block: %d at %p\n", x, &x);
    }
    // 块中内存被释放隐藏的x恢复 x = 30
    printf("x in outer block: %d at %p\n", x, &x);

    while (x++ < 33)
    {
        int x = 100;
        x++;
        printf("x in while loop: %d at %p\n", x, &x);
    }
    printf("x in outer block: %d at %p\n", x, &x);
}

没有花括号时

void forc()
{
    int n = 8;
    printf("  Initially, n = %d at %p\n", n, &n);
    for (int n = 1; n < 3; ++n)
        printf("      loop 1:n = %d at %p\n", n &n);
    // 离开循环后原始的你又起作用了
    printf("After loop 1:n = %d at %p\n", n &n);
    for (int n = 1; n < 3; ++n)
    {
        printf("loop 2 index n = %d at %p\n", n, &n);
        // 重新初始化的自动变量,作用域没有到循环里的n
        int n = 6;
        printf("      loop 2:n = %d at %p\n", n, &n);
        // 起作用的仍然是循环中的n
        n++;
    }
    // 离开循环后原始的n又起作用了
    printf("      loop 2:n = %d at %p\n", n, &n);
}

输出为

  • 寄存器变量

使用关键字register,储存在CPU的寄存器中,存储在最快的可用内存中。

  • 块作用域的静态变量

? 首先要明确概念静态变量并不是指值不改变的变量,而是指它在内存中的位置不变。具有文件作用域的静态变量自动具有静态存储期。

前面提到我们可以创建一个静态存储期,块作用域的局部变量,这种变量和自动变量一样具有相同的作用域,但是在程序离开块时并不会消失,

void trystat();

int main()
{
    int count = 1;
    for (count = 1; count <= 3; count++)
    {
        printf("Here comes iteration %d:\n", count);
        trystat();
    }
    trystat();
    return 0;
}

void trystat()
{
    int fade = 1;
    static int stay = 1;
    printf(" fade = %d and stay = %d\n", fade++, stay++);
}

输出:

? 可以看出每次离开块fade变量的值都会被重新的初始化,而stay只是在编译函数void trystat()的时候被初始化了一次,在离开自己函数体的块和for循环块之后都会递增,说明stay访问的对象一直存在并没有像自动变量一样被释放掉。

  • 外部链接的静态变量

? 具有外部链接、静态存储期和文件作用域,属于该类别的变量属于外部变量。只需要把变量的声明放在所有函数的外面就创建了一个外部变量。为了表明该函数使用了外部变量,需要使用关键字extern来再次申明。如果在一个源文件中使用的外部变量声明在了另一个源文件中,则必须要使用extern来申明。

外部变量可以显示初始化,如果没有则会被默认初始化为0。

  • 内部链接的静态变量

具有文件作用域、静态存储期和内部链接,在所有函数外用static来声明一个变量就是内部链接的静态变量。

例:

static int val = 1;
int main()
{
    ...
}

普通的外部变量可以用于程序中的任意一个函数处,但是内部链接的静态变量只能用于同一个文件中的函数。都可以使用extern说明符,在函数中重复任何声明文件作用域变量并不会改变他们的链接属性。

例:

int global = 1;
static int local_global = 2;
int main
{
    extern int global = 1;
    extern int local_global = 2;
    ...
}

只有在多文件中才能区别内部链接和外部链接的重要性。

总结一下存储类别的说明符中关键字共有六个autoregister_Thread_localstaticexterntypedef ,其中staticextern的含义取决于上下文,

原文地址:https://www.cnblogs.com/TJTO/p/11795786.html

时间: 2024-11-05 06:13:02

C语言存储类别和链接的相关文章

C语言--存储类、链接和内存管理

注:此文为<C Primer Plus>一书中的部分总结,写下来方便以后参考. 用于存储程序数据的内存可用存储时期.作用域和链接来表征. 存储时期可以使静态的.自动的或者分配的.①如果是静态的,内存在程序开始执行时被分配,并行程序运行时一直存在.②如果是自动的,变量所用内存在程序执行到该变量定义所在代码块时开始分配,在退出代码块时释放.③如果是分配的内存,内存通过调用malloc()(或其他相关函数)分配,通过调用函数free()释放. 作用域决定哪一部分程序可以访问某个数据.在所有函数之外定

存储类别、链接和内存管理

C变量作用域:块作用域.函数作用域.函数原型作用域.文件作用域. C变量的3种链接属性:外部链接.内部链接.无链接.前三种作用域变量都是无链接(仅在作用域内被使用):文件作用域变量根据定义形式来看,如果是static则为内部链接(仅在本文件内被使用),否则为外部链接(能被多个文件共享). 存储期:静态存储期(文件作用域变量,存在于整个程序的执行时间内) 线程存储期(用于并发程序设计,从被声明到线程结束) 自动存储期(块作用域变量,从进入块到块结束:VLA变长数组略有不同,是从被声明到块结束) 综

C/C++ 存储类别

table { margin: auto; } 本文介绍 C/C++ 中的存储类别.所谓的"存储类别"究竟是什么意思? 存储类别主要指在内存中存储数据的方式,其大致牵涉到变量的三个方面 -- 作用域.链接性和存储期,也就是说这三个方面决定了存储类别.下面先解释这三个概念,再介绍在 C/C++ 中的表示形式. 存储类别定义 作用域 (scope) 描述程序中可访问变量的区域,主要有块作用域 (block scope) 变量和 文件作用域 (file scope) 变量,平常我们也分别用局

c语言 变量的存储类别以及对应的内存分配?

<h4><strong>1.变量的存储类别</strong></h4>从变量值存在的角度来分,可以分为静态存储方式和动态存储方式.所谓静态存储方式指在程序运行期间由系统分配固定的存储空间的方式(<strong>程序开始执行时分配,在程序完毕时释放,在程序过程中它们占据国定的存储单元,而不是动态分配和释放</strong>).而动态存储方式在运行期间根据需要进行动态存储方式(<strong>在程序过程中申请和释放的一些空间&

C语言杂谈(三)存储类别

本文讨论C语言中的存储类别,包括数据在内存的存储.变量的存储类别.函数的存储类别.生存周期.下图为计算机的存储空间,有寄存器和内存. 一.存储区域 1.寄存器:存放立即参加运算的数据. 2.系统区:存放系统软件. 3.用户程序代码区:存放用户程序的程序代码. 4.库程序代码区:存放库函数的代码. 5.数据区,分为堆区.栈区和静态存储区. (1)堆区:存放动态变量,即由malloc申请的动态变量. (2)栈区:存放自动存储类型的变量,包括函数和复合语句中的局部变量等. (3)静态存储区:存放具有显

C语言变量的存储类别

我们知道,从变量的作用域(即从空间)角度来分,可以分为全局变量和局部变量. 从另一个角度,从变量值存在的作时间(即生存期)角度来分,可以分为静态存储方式和动态存储方式. 静态存储方式:是指在程序运行期间分配固定的存储空间的方式. 动态存储方式:是在程序运行期间根据需要进行动态的分配存储空间的方式. 用户存储空间可以分为三个部分: 程序区: 静态存储区: 动态存储区. 全局变量全部存放在静态存储区,在程序开始执行时给全局变量分配存储区,程序行完毕就释放.在程序执行过程中它们占据固定的存储单元,而不

C语言中存储类别又分为四类:自动(auto)、静态(static)、寄存器的(register)和外部的(extern)。

除法运算中注意: 如果相除的两个数都是整数的话,则结果也为整数,小数部分省略,如8/3 = 2:而两数中有一个为小数,结果则为小数,如:9.0/2 = 4.500000. 取余运算中注意: 该运算只适合用两个整数进行取余运算,如:10%3 = 1:而10.0%3则是错误的:运算后的符号取决于被模数的符号,如(-10)%3 = -1;而10%(-3) = 1. -- 1.  用关键字auto定义的变量为自动变量,auto可以省略,auto不写则隐含定为"自动存储类别",属于动态存储方式

c语言 作用域、存储期、链接属性汇总

1.作用域 块作用域:用{}阔起来的,从声明开始到"}" 结束 函数作用域:goto(标识符) 的作用域为整个函数. 函数原型作用域:函数声明开始,函数声明结束而结束 文件作用域:整个文件或者程序 2.链接 无链接:即只在其作用域内可见 内链接:即在从声明到文件结束都是可见的 外链接 :多个文件或者整个程序都可见 3.存储期 静态存储期:在整个程序都是占有内存的 线程存储期:thread_local,其声明后会给每个线程分配一个单独的私有备份 自动存储期:局部变量通常都自动为auto

C存储类、链接小结

参考<C Primmer Plus> 首先唠唠C语言关键字: 数据类型14个:            void,  char(1字节),  int(4字节), short(2字节),  long(4字节),  signed(4字节), unsigned(4字节),            float(4字节),  double(8字节),  struct, union, enum, typedef, sizeof 存储类控制类型6个:            auto, static, exter