c c area - yaokun123/php-wiki GitHub Wiki

作用域

一、变量作用域

1、局部变量

在{}之内定义的变量

作用域:在定义变量的{}内有效
生命周期(什么时候开辟空间-》什么时候释放空间):程序运行至变量定义处开辟空间,所在的函数结束后释放空间
未初始化的值:随机

2、静态局部变量

在{}之内定义的变量,前面加上static关键词修饰的变量
作用域:在定义变量的{}内有效
生命周期:main函数运行之前就已经开辟空间,程序结束之后才会释放空间
未初始化的值:对应类型的初始化值

#include<stdio.h>
void fun(){
    static int a = 1;//main函数运行之前就已经开辟空间,下次再执行到就忽略
    a += 1;
    printf("%d\n",a);
}
int main(){
    fun();//2
    fun();//3
    return 0;
}

3、全局变量

在函数之外定义的

作用域:作用于整个工程,所有文件
生命周期:main函数运行之前就已经开辟空间,程序结束之后才会释放空间
未初始化的值:对应类型的初始化值

4、静态全局变量

在函数之外定义的,并且加上static修饰的变量

作用域:作用于当前文件(不能申明,也不能再其他文件使用)
生命周期:main函数运行之前就已经开辟空间,程序结束之后才会释放空间
未初始化的值:对应类型的初始化值

注意在.h文件中,全局变量只申明不定义,定义只放在.c文件中

不同的作用域可以重名

普通函数就是全局函数,静态函数就是函数定义时添加static关键词,只作用于当前文件

二、内存分布

内存都是提前规划好的,编译完成之后就知道了。只有局部变量是运行的时候分配的

三、内存处理函数

1、memset:void *memset(void *s,int c,size_t n);

将s的内存区域的前n个字节以参数c填入

#include<stdio.h>
#include<string.h>

int main(){

    int a = 10;
    //a = 0;->memset()
    memset(&a,0,sizeof(a));
    printf("%d\n",a);

    char buf[10] = "";
    strcpy(buf,"hello");
    printf("%s\n",buf);
    memset(buf,0,sizeof(buf));
    printf("%s\n",buf);

    memset(buf,'a',sizeof(buf)-1);
    printf("%s\n",buf);
    return 0;
}

2、memcpy:void *memcpy(void *dest,const void *src,size_t n);

拷贝src所指的内存内容前n个字节到dest所指向的内存地址上。

#include<stdio.h>
#include<string.h>

int main(){

    int a[10] = {1,2,3,4,5,6,7,8,9,10};
    int b[10] = {0};

    memcpy(b,a,sizeof(int)*5);//拷贝前5个元素,20个字节
    for(int i = 0;i<sizeof(b)/sizeof(b[0]);i++){
        printf("%d ",b[i]);
    }
    printf("\n");
    return 0;
}

3、memmove

memmove()功能用法和memcpy()一样,区别在于:dest和src所指的内存空间重叠时,memmove仍然能够处理,不过指向效率比memcpy低一些

4、memcmp

比较两个内存前n个字节大小

内存操作函数遇到0都不会结束操作,而str字符串操作函数遇到0都会结束

四、堆区内存的申请和释放

1、malloc:void *malloc(size_t size);free:释放堆内存地址

在内存的动态存储区(堆区)中分配一块长度为szie字节的连续区域,用来存放类型说明符指定的类型,分配的内存空间内容不确定,一般使用memset初始化

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

int main(){
    int *p = (int *)malloc(sizeof(int));

    *p = 10;
    printf("%d\n",*p);

    free(p);//释放
    return 0;
}

malloc申请的空间不能释放两次,申请一次释放一次。free参数必须是上一次malloc申请过的,不能改变这个地址

五、内存泄露

只申请,不释放

六、返回变量地址

局部变量地址不能返回

#include<stdio.h>
int * fun(){
    int a = 10;
    a *= 10;
    return &a;
}
int main(){

    int *p = fun();

    *p = 200;//p所指向的空间已经被释放

    printf("%d\n",*p);
    return 0;
}

静态局部变量地址可以返回

#include<stdio.h>
int * fun(){
    static int a = 10;
    a *= 10;
    return &a;
}
int main(){

    int *p = fun();

    *p = 200;

    printf("%d\n",*p);
    return 0;
}

七、返回堆区的地址

#include<stdio.h>
#include<stdlib.h>
int * fun(){
    int *p = (int *)malloc(sizeof(int));//malloc申请的堆空间,如果不手动释放,要等到程序结束才会释放
    return p;
}
int main(){

    int *k = fun();

    *k = 200;

    printf("%d\n",*k);
    return 0;
}

注意释放:

#include<stdio.h>
#include<stdlib.h>
int * fun(){
    int *p = (int *)malloc(sizeof(int));//malloc申请的堆空间,如果不手动释放,要等到程序结束才会释放
    return p;
}
int main(){

    int *k = fun();

    k = "abc";//指向新地址,堆内存空间没有指向,k指向文字常量区
    //free(k);//这里不能不释放

    return 0;
}
⚠️ **GitHub.com Fallback** ⚠️