第12章,存储类别、链接和内存管理

12.1  存储类别

目前程序示例,从硬件来看,被存储的每个值都占用一定的屋里内存,C语言把这样一块内存称为对象,对象可以存储一个或多个值,

声明变量可以访问对象,标识符可以来指定特定的对象内容。

存储期来描述对象在内存中保留了多长时间,标识符用于访问对象,可用作用域和链接来描述标识符。

12.1.1  作用域

作用域来描述程序中可访问标识符的区域。

块作用域:整个函数是一个块,函数中的任意语句也是一个块,块作用域变量可见范围是从定义处到包含该定义的结尾

函数作用域:仅用于goto语句的标签。

函数原型作用域:从形参定义处到原型声明处结束。

文件作用域:变量定义在函数外面具有文件作用域。

注意:编译器源代码文件和所有头文件都看成是一个包含信息的单独文件,被称为翻译单元。描述一个具有文件作用域的变量,它实际可见范围是整个翻译单元。

12.2  链接

c变量有3种属性,外部链接,内部链接,无链接。

使用存储类别说明符static的是内部链接。

12.1.3  存储期

作用域和链接描述了标识符的可见性,存储期描述了通过这些标识符访问对象的生命周期。

c语言有4种存储期:静态存储期。线程存储期,自动存储器,动态分配存储期。

静态存储期:它在程序执行时一直存在,文件作用域变量具有静态存储期。

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

自动存储期:快作用域变量具有自动存储期。

动态分配存储期:手动创建,手动释放。

 12.1.4  自动变量

属于自动存储类型类别的变量具有自动存储期,块作用域且无链接。

默认情况:在块或函数头中任何变量都属于自动存储类别,也可以显式的使用关键字auto

c99特性:作为for循环或if语句的一部分,即使不使用花括号也是一个块,完整来说整个循环是它所在的子块,循环体是整个循环的子块。

12.1.5  寄存器变量

register  int  n  请求寄存器变量。

12.1.6  块作用域的静态变量

即块作用域变量在函数结束后任然存在。

12.1.7  外部链接的静态变量

具有文件作用域和外部链接,静态变量。

如果为了源代码使用的外部变量在另一个文件中,必须使用extern在该文件中重新声明变量。

int tern=1//定义式声明

int  main

{extern int  tern;//引用式声明

}

12.1.8  内部链接的静态变量

具有内部链接,静态变量,文件作用域。

12.1.9多文件

12.1.10  存储类别说明符

auto:只用于块作用域的变量声明,由于在块中声明的变量本身就是自动存储,所以使用auto只是为了明确表示使用与外部变量同名的局部变量的意图。

register:只用于块作用域,它把变量归于寄存器类别。

static:用于说明创建的变量具有静态存储期,如果static用于文件作用域声明,则该变量受限于文件。如果用于块作用域,则该变量具有静态存储。

extern:说明声明的变量定义在别处

_Thread_local,typedef

12.1.11  存储类别和函数

12.1.12  存储类别的选择

12.2  随机函数和静态变量

函数位于stdlib.h头文件中

rand()产生随机数,srand()产生随机数种子。

函数位于time.h头文件中

例:srand(unsigned  int)time(NULL)获取随机数种子。

12.4  分配内存:malloc()和free()

声明数组的3中方法

声明数组时,用常量表达式表示数组维度,用数组名来访问数组的元素,可以用静态内存或自动内存来创建。

声明变长数组(c99)用变量表达式来表示数组维度,具有这种特性的数组只能在自动内存中创建

声明一个指针,调用malloc()将其返回值赋给指针,使用指针访问数组元素,该指针可自动或静态。double *ptd=(double*)malloc (n*sizeof(double))

12.4.1  free()的重要性

一定要释放内存。

12.4.2  calloc()函数

long *ptd=(long *)calloc(n,sizeof(long))

在ANSI后calloc类似malloc返回void的指针,所以要使用强制类型转化符,接受两个无符号整数作为参数,ANSI规定为size_t类型。

12.4.3  动态内存分配和变长数组

区别:变长数组是自动存储类型。

12.4.4  存储类别和动态内存分配

理想化模型:内存分为三部分

一部分为具有外部链接,内部链接和无链接的静态内存使用、一部分供自动变量使用、一部分供动态内纯分配。

静态存储类别所用内存数量在编译时确定。

自动存储类别在程序进入变量定义所在块时存在,离开块时消失。(一般作为桟处理)

动态内存在调用malloc()或相关函数时存在,在调用free()后释放。

12.5  ANSI C类型限定符

c99新增可以在一条声明中多次使用同一个限定符

12.5.1  const类型限定符

const  float* pt  表示不能通过pt修改它指向的值。

float* const pt  表示不能修改pt的值。

简而言之,const放在*左侧任意位置,限定了指针指向的数据不能改变,放在*右侧,指针本身不能改变。

12.5.2  volatile类型限定符

volatile表示计算机,代理可能改变该变量的值,表示该值有可能发生变化。

12.5.3  restrict类型限定符

只能用于指针,表示该指针是访问数据对象唯一且初始的方式

12.5.4  _Atomic类型限定符(c11)

_Atomic  int  hogs://int  hogs

atomic_store(&hogs,12)//  hogs=12

12.9  编程练习

5.

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
    int num[100];
    int n;
    srand((unsigned int)time(NULL));
    for (int i = 0; i < 100; i++)
    {
        num[i]=(rand()%10)+1;
        printf("(%-2d)",num[i]);
    }
    puts("");
    for (int i = 0; i < 100; i++)
    {
        for (int j = i+1; j < 100; j++)
        {
            if (num[i]<num[j])
            {
                n=num[i];
                num[i]=num[j];
                num[j]=n;
            }  
        }  
        printf("(%-2d)",num[i]);  
    }  
    system("pause");
}

9.

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<string.h>
 4 #include<time.h>
 5 #include<ctype.h>
 6 int main()
 7 {   
 8     int word_num;
 9     char  nu[100];
10     puts("请输入单词数");
11     scanf("%d",&word_num);
12     char **ch=(char **)malloc(word_num*6*sizeof(char));
13     while (getchar()!='\n')
14         continue;
15     puts("请输入字符串");
16     gets(nu);
17     puts(nu);
18     int n=0;
19     for (int i = 0,j=0; i < strlen(nu)+1; i++)
20     {
21         if(isalnum(nu[i])&&(n==0))
22         {
23             n=1;
24             ch[j]=&nu[i];
25             j++;
26         }
27         else if(!isalnum(nu[i])&&(n==1))
28         {
29             n=0;
30             nu[i]='\0';
31         }        
32     }
33     printf("%u",sizeof(ch));
34     for (int i = 0; i < word_num; i++)
35     {
36         printf("%s",ch[i]);
37     }  
38 
39     
40     
41     
42     system("pause");
43 }

9.

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
  int main()
  {   
      int word_num;
      char  nu[100];
     puts("请输入单词数");
     scanf("%d",&word_num);
     char **ch=(char **)malloc(word_num*sizeof(char*));
     while (getchar()!='\n')
         continue;
     puts("请输入字符串");
     gets(nu);
    int num=strlen(nu);
     for (int i = 0,n=0; i < num; i++)
     {
        if(isalnum(nu[i])&&(n==0))  
            n=1;
        else if(!isalnum(nu[i]))
        {
            n=0;
            nu[i]='\0';
        }    
    }
    for (int i = 0,n=0,j=0; i < num; i++)
     {
         if(isalnum(nu[i])&&(n==0))
         {
             ch[j]=(char *)malloc(strlen(&nu[i])*sizeof(char));
             ch[j]=&nu[i];
             j++;
             n=1;
         }
        else if(!isalnum(nu[i]))
            n=0;    
    }
    for (int i = 0; i <  word_num; i++)
     {
         puts(ch[i]);
     }   
     system("pause");
        return 0;
 }

猜你喜欢

转载自www.cnblogs.com/suwencjp/p/12456915.html