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

作用域

  1. 作用域描述程序中可以访问标识符 的区域.
  2. 一个C变量的作用域可以是块作用域、函数作用域、函数原型作用域或文件作用域。
  3. 块是用一对花括号括起来的代码区域
#include <stdio.h>

int main(void)
{
    int x;
    x = 1;
    printf("%d\n", x);
    {
        int x = 5;          // 新的x 
        printf("%d\n" , x); // x作用域结束 
    }
    printf("%d\n", x);      // 原来的x 

    return 0;
}

链接

C变量用3种属性:外部链接、内部链接或无链接。具有块作用域、函数作用域或函数原型作用域的变量都是无链接变量。
简单来说就是有链接的变量都是全局变量。不过之间也有点不同

存储期

C对象有4中存储期: 静态存储期、线程存储期、自动存储期、动态分配存储期。

  • 静态存储期:一直存在
  • 线程存储期:从被声明时到线程结束一直存在。
  • 自动存储期:当程序进入这些块时分配内存。推出时释放内存
  • 动态分配:用特殊的关键字来创建和释放内存


    image.png

块作用域的静态变量

#include <stdio.h>
void trystat(void);

int main(void)
{
    int count;

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

void trystat(void)
{
    int fade = 1;           //执行3次都是1
    static int stay = 1;    //会记录住原来的

    printf("fade = %d and stay = %d\n", fade++, stay++);
}

image.png

内部链接的静态变量

该存储类别的变量具有静态存储期、文件作用域和内部链接。定义在所用函数外部(和上面那个不一样)

static int svil = 1;   //静态变量,内部链接
int main(void)
{
      extern int svil;   //使用定义在别处的
}
注:作用域只有本文件有效

外部链接的静态变量

int Errupt;
int main(void)

1.不使用全局变量, 从写12.4

#include <stdio.h>
int critic(void);

int main(void)
{
    int units;

    printf("How many pounds to a firkin of butter?\n");
    scanf("%d", &units);
    while (units != 56)
    {
        units = critic();
    }
    printf("You must have looked it up!\n");

    return 0;
}

int critic(void)
{
    int i;
    printf("No luck, my friend. Try again.\n");
    scanf("%d", &i);
    return i;
}

2

//pe12-2b.c

#include <stdio.h>
#include "pe12-2a.h"

int main(void)
{
    int mode;

    printf("Enter 0 for metric mode, 1 for US mode: ");
    scanf("%d", &mode);
    while (mode >= 0)
    {
        set_mode(mode);
        get_info();
        show_info();
        printf("Enter 0 for metric mode, 1 for US mode");
        printf(" (-1 to quit): ");
        scanf("%d", &mode);
    }
    puts("Done");
    
    return 0;
}

//pe12-2a.c

#include <stdio.h>
#include "pe12-2a.h"

static int mode = 0;
static double distance;
static double energy;

void set_mode(int n)
{
    if (n == 0 || n == 1)
        mode = n;
    else
        printf("Invalid mode specified.Mode %s used.\n", (mode ? "1(US)" : "0(metric)"));
}

void get_info(void)
{

    if (mode == 0)
    {
        printf("Enter distance traveled in kilometers: ");
        scanf("%lf", &distance);
        printf("Enter fuel consumed in liters: ");
        scanf("%lf", &energy);
    }
    
    else
    {
        printf("Enter distance traveled in miles: ");
        scanf("%lf", &distance);
        printf("Enter fuel consumed in gallons: ");
        scanf("%lf", &energy);
    }
    
}

void show_info(void)
{
    double consuption;
    if (mode == 0)
    {
        consuption = energy / distance * 100;
        printf("Fuel consumption is %.2lf liters per 100 km\n", consuption);
    }
    else
    {
        consuption = distance / energy;
        printf("Fuel consumption is %.1lf miles per gallon\n", consuption);
    }

}

//pe12-2a.h

void set_mode(int);

void get_info(void);

void show_info(void);

3.重写上面

//pe12-2b.c

#include <stdio.h>
#include "pe12-2a.h"

int main(void)
{
    int mode;
    int num = 0;
    double distance, energy;

    printf("Enter 0 for metric mode, 1 for US mode: ");
    scanf("%d", &mode);
    while (mode >= 0)
    {
        num = set_mode(num, mode);
        get_info(num, &distance, &energy);
        show_info(num, distance, energy);
        printf("Enter 0 for metric mode, 1 for US mode");
        printf(" (-1 to quit): ");
        scanf("%d", &mode);
    }
    puts("Done");
    
    return 0;
}

//pe12-2a.c

#include <stdio.h>
#include "pe12-2a.h"


int set_mode(int n,int m)
{
    if (m == 0 || m == 1)
        n = m;
    else
        printf("Invalid mode specified.Mode %s used.\n", (n ? "1(US)" : "0(metric)"));
    return n;
}

void get_info(int n, double *distance, double *energy)
{

    if (n == 0)
    {
        printf("Enter distance traveled in kilometers: ");
        scanf("%lf", distance);
        printf("Enter fuel consumed in liters: ");
        scanf("%lf", energy);
    }
    
    else
    {
        printf("Enter distance traveled in miles: ");
        scanf("%lf", distance);
        printf("Enter fuel consumed in gallons: ");
        scanf("%lf", energy);
    }
    
}

void show_info(int mode , double distance, double energy)
{
    double consuption;
    if (mode == 0)
    {
        consuption = energy / distance * 100;
        printf("Fuel consumption is %.2lf liters per 100 km\n", consuption);
    }
    else
    {
        consuption = distance / energy;
        printf("Fuel consumption is %.1lf miles per gallon\n", consuption);
    }

}

//pe12-2a.h


int set_mode(int, int);

void get_info(int, double *, double *);

void show_info(int, double, double);

4

#include <stdio.h>

int ret_num(void);

int main(void)
{
   int i;
   ret_num();
   i = ret_num();
   printf("%d\n", i);
}

int ret_num(void)
{
   static int count = 0;
   return ++count;
}

5

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define SIZE 100

void stsrt(int *st[], int num);

int main(void)
{
    int number[SIZE];
    int i;
    int *p[SIZE];
    
    srand((unsigned int) time(0));
    for ( i = 0; i < SIZE; i++)
    {
        number[i] = rand() % 10 + 1;
        p[i] = &number[i];
    }
    stsrt(p, SIZE);
    puts("排序后:"); 
    for ( i = 0; i < SIZE; i++)
    {
        printf("%d ", *p[i]);
    }
    
    
    printf("\n");
    puts("排序前:");
    for ( i = 0; i < SIZE; i++)
    {
        printf("%d ", number[i]);
    }

    return 0;
}

void stsrt(int *st[], int num)
{
    int *temp;
    int top, seek;
    int i = 0;
    for ( top = 0; top < num - 1; top++)
    {
        for ( seek = top + 1; seek < num; seek++)
        {
            if ( *st[top] < *st[seek])
            {
                temp = st[top];
                st[top] = st[seek];
                st[seek] = temp;
            }
            
        }
        
    }
}

6出自:https://blog.csdn.net/o707191418/article/details/81904734

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
    int random_[10] = {0};
    int i, num;

    srand((unsigned int) time(0));
    for(i = 0; i < 100; i++)
    {
        num = rand() % 10 +1;
        random_[num - 1]++;
    }
    for ( i = 0; i < 10; i++)
    {
        printf("%d : %d\n", i + 1, random_[i]);
    }
    
}

7

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int roll_n_dice(int , int );
int main(void)
{
    int size, dice, many, status;
    int i, roll;

    srand((unsigned int) time(0));
    puts("Enter the number of sets; enter q to stop.");
    while (scanf("%d", &many) == 1 && many > 0)
    {
        puts("How many sides and how many dice?");
        if ((status = scanf("%d %d", &size, &dice)) != 2)
        {
            if (status == EOF)
                break;
            else
            {
                puts("You should have entered an integer.");
                puts("Let's begin again.");
                while (getchar() != '\n')
                    continue;
                puts("Enter the number of sets; enter q to stop.");
                continue;
            }
            
        }
        printf("Here are %d sets of %d %d-sided throws.\n", many, dice, size);
        for ( i = 0; i < many; i++)
        {
            roll = roll_n_dice(dice, size);
            printf("%d ", roll);
        }

        puts("\nEnter the number of sets; enter q to stop.");
        
    }
    
}

int roll_n_dice(int dice, int size)
{
    int total = 0;
    int i;
    if (size < 2)
    {
        printf("Need at least 2 sides.\n");
        return -2;
    }
    if (dice < 1)
    {
        puts("Need at lease 1 die.\n");
        return -1;
    }
    for ( i = 0; i < dice; i++)
    {
        total += rand() % size + 1;
    }
    return total;
}

8

#include <stdio.h>
#include <stdlib.h>

int * make_array(int elem, int val);
void show_array(const int ar[], int n);

int main(void)
{
    int * pa;
    int size;
    int value;

    printf("Enter the number of elements:");
    while (scanf("%d", &size) == 1 && size > 0)
    {
        printf("Enter the initialization value: ");
        scanf("%d", &value);
        pa = make_array(size, value);
        if (pa)
        {
            show_array(pa, size);
            free(pa);
        }
        printf("\nEnter the number of elements (<1 to quit): ");
        
    }
    printf("Done.\n");
    return 0;
}

int * make_array(int elem, int val)
{
    int *p;
    int i;
    p = (int *) malloc(elem * sizeof(int));
    for ( i = 0; i < elem; i++)
    {
        p[i] = val;
    }
    
    return p;
}

void show_array(const int ar[], int n)
{
    int i;
    for ( i = 0; i < n; i++)
    {
        printf("%d ", ar[i]);
        if ((i + 1) % 8 == 0)
            printf("\n");
    }
    
}

9https://blog.csdn.net/o707191418/article/details/81904734

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 64

int main(void)
{
    char **p;   //存储字符串
    char *temp; //用于零时存储
    int words;  //单词数量
    int len;    //计算长度,方便后面拷贝
    int i;

    printf("How many words do you wish to enter? ");
    scanf("%d", &words);
    printf("Enter %d words now:\n", words);
    p = (char **) malloc(words * sizeof(char *));   //数组里的每一个元素是一个指针,指向char类型(数组里存储的是指向char类型的指针)
    temp = (char *) malloc(SIZE * sizeof(char));    //分配一段内存,用于存储字符串
    for ( i = 0; i < words; i++)
    {
        scanf("%s", temp);      //输入字符串,scanf将空格回车视为一个单词的结束
        len = strlen(temp);     //计算单词占多少空间
        p[i] = (char *) malloc((len + 1) * sizeof(char));   //p里面每个元素都是一个指针,分配内存让他指向该内存,+1是为了存储\0
        strcpy(p[i], temp);     //拷贝
    }
    free(temp);     //释放temp的空间
    for ( i = 0; i < words; i++)
    {
        puts(p[i]);
    }
    free(p);    //释放p空间
    
    return 0;

}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容