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

一、static关键字

(1)在修饰变量的时候,static 修饰的静态局部变量只执行初始化一次,而且延长了局部变量的生命周期,直到程序运行结束以后才释放。

(2)static 修饰全局变量的时候,只能在当前.c文件中访问,不能在其它文件中访问,即便是 extern 外部声明也不可以。

(3)static 修饰一个函数,该函数只能是当前.c文件能调用,其他.c不能调用。static 修饰的变量存放在全局数据区的静态变量区,包括全局静态变量和局部静态变量,都在全局数据区分配内存。初始化的时候自动初始化为 0。

(4)不想被释放的时候,可以使用static修饰。比如修饰函数中存放在栈空间的数组。如果不想让这个数组在函数调用结束释放可以使用 static 修饰。

(5)考虑到数据安全性和程序耦合度时,当只想当前文件使用时优先考虑static修饰变量和函数养成良好的编程习惯。

1.静态局部变量

#include<stdio.h>

void f(void)
{
    int n = 10;

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

void f_static(void)
{
    static int n = 10;

    printf("static n=%d\n", n);
    n++;
    printf("n++=%d\n", n);
}

int main(void)
{
    f();//10 11
    printf("--------------------\n");
    f_static();//10 11
    printf("--------------------\n");
    f();//10 11
    printf("--------------------\n");
    f_static();//11 12

    return 0;
}
转载于https://blog.csdn.net/guotianqing/article/details/79828100

再次调用f_static函数输出11 12的原因是:

静态变量是指变量在内存中的地址不变,但值可改变,局部变量每次都会被初始化,而静态局部变量被初始化一次。

1.程序进程中内存中分布为栈区、堆栈增长区、堆区、其他段、.bss段、.data段、text段。

data段:在程序中所有赋了初值的全局变量,存放在这里

.bss段:在程序中没有初始化的全局变量;内核将此段初始化为0。

栈:增长方向:自顶向下增长;自动变量以及每次函数调用时所需要保存的信息(返回地址;环境信息)

堆:动态存储部分。

局部静态变量:内存中的位置是静态存储区,会被程序自动初始化为0,作用域为局部作用,当定义它的函数或语句结束时,作用域随之结束,但它离开作用域时,并没有被销毁,仍然在内存当中,直至程序结束,不能再次对它进行访问。若想访问时需再次执行该函数,程序才能访问它所指定的对象,其他函数想要使用可通过该函数提供的存储区地址间接访问该对象,例如通过指针形参或返回值

静态存储区是指程序执行过程中它一直都存在,文件作用域变量具有静态存储区,块区域变量具有静态储存区。

2.静态全局变量

因静态全局变量仅对当前文件可见,其他文件不可访问,所以其他文件定义相同的变量互不影响,降低了程序模块之间的耦合,若是需要其他文件访问时,可定义全局变量(其他文件利用extern引用使用即可)。

静态全局变量:内存中的位置是静态存储区,会被程序自动初始化为0,作用域是整个文件。

3.静态函数

在函数的返回类型前加上关键字static,函数就被定义成为静态函数。
 函数的定义和声明默认情况下是extern的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。

定义静态函数的好处:
1.其他文件中可以定义相同名字的函数,不会发生冲突
2. 静态函数不能被其他文件所用。

存储说明符auto,register,extern,static,对应两种存储期:自动存储期和静态存储期

auto register 只能用于块作用域的变量声明中。register它把变量归为寄存器存储类别。

自动变量例子:

#include<stdio.h>
int main(){
        int x = 30;//局部变量,作用域是开始到结束
        printf("%d,%p\n",x,&x);
        {
                int x = 77;//新的x 占用外部x的内存地址,当块函数结束地址还给外部
x
                printf("%d,%p\n",x,&x);
        }
        while(x++<33){
                int x = 100;//新的X
                printf("%d,%p\n",x,&x);
        }
        return 0;
}
自动变量初始化方式可有:
int main(){
    int  x;
    int y =10;
或
    int x = 1;
    int y = 2 * x;
}
自动变量不会初始化,需显式初始化。

全局变量:

若全局变量,未初始化会被自动初始化为0
int x = 10;
int y = 3 + 20;
int z = x * 2 ;//错误,初始化方式,与自动变量不同,不能这样进行初始化。

例子

 :i

 gcc demon3.c demon4.c -o test

malloc()函数 该函数接受所需的内存字节数,进行分配内存(匿名形式),且返回动态分配内存块的首地址,通过将地址赋值给指针变量,并使用指针访问这块内存。通常是以指向void的指针(通用指针),再通过强制类型转换到所匹配类型的指针。

例子:

/*动态分配数组 demon5.c gcc demon5.c -0 demon5*/
#include<stido.h>
#include<stdlib.h>
int main(void){
    double *ptd;
    int max;
    int number;
    int i = 0;
    puts("what is maximum number of type double entries");
    if (scanf("%d",&max)!=1)
    {
        puts("Number not corrently entered = = bye");
        exit(EXIT_FAILURE);
    }
    ptd = (double *) malloc(max*sizeof(double));
    if (ptd == NULL)
    {
        puts("Memory allocation failed.bye");
        exit(EXIT_FAILURE);//执行失败
    }
    puts("Enter the value to array");
    while(i < max && scanf("%d",&ptd[i])==1)
        ++i;//先计算再操作
    printf("Here are your %d entries:\n",number=i);
    for ( i = 0; i < number; i++){
          printf("%7.2f",ptd[i]);
          if (i%7==6)
          {
            puts("\n");
          }  
    }
    if (i % 7 !=0)
    {
        puts("\n");
    }
    puts("Done");
    free(ptd);//释放malloc()函数分配的内存,可以避免内存泄漏问题。
    return 0;
}

calloc()函数 作用与malloc()函数类似:

声明规则有所不同

long *test;
test = (long *) calloc(100,sizeof(long));//100*4=400 内存大小

const float * pf;//指向float类型的常量值 pf本身值可以改变,但是指向的float的不能被改变
float * const pf;//常量指针 ,本身值不可以改变,但是指向的float的值可以改变,也就是可以被其他的float地址值再次赋值。
const float * const pf;//两个都是常量不可以改变。

volatile int local //local是一个易变的位置
volatile int *ploc //ploc是一个指向易变的位置的指针。

restrict关键字,它只能用于指针,表明该指针是访问数据对象的位置且初始方式
int arr[10];
int * restrict restart = int(*) malloc(10*sizeof(int));//唯一且初始方式访问数据
int * pf = ar;
 
_Atomic类型限定符 常用于多线程中。当一个线程对一个原子类型的对象执行原子操作时,其他线程不能访问该对象。



以上内容个人学习总结,若有错误请谅解,谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值