u=3795680347,564522082&fm=15&gp=0.jpg
    1.操作系统把硬盘代码读取到内存
    2.操作系统把c代码分成四个区
    3.操作系统找到main函数入口执行

    内存四区:
    一个由c/c++编译的程序占用的内存分为以下几个部分
    1.栈区stack:由编译器自动分配释放,存放函数的参数值,局部变量值等。其操作方式类似于数据结构中的栈。
    2.堆区heap:一般由程序员分配释放,若程序员不释放,程序结束时可能由系统回收。
    3.数据区:主要包括静态全局区和常量区,如果站在汇编角度细分的话还可以分为很多小的区
    全局区(静态区)static:全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。
    常量区:常量字符串就是放在这里的。
    程序结束后由系统释放。
    4.代码区:存放函数体的二进制代码。

    堆区分析
    1.strcpy函数的作用:
    原型声明:char strcpy(chardest,const char *src);
    功能:把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间
    说明:src和dest所直内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串
    返回指向dest 指针
    2.堆区不会自动释放,需要手动释放
    3.Free的意思不是清空内存而是解除这个指针的绑定关系,原先只有指针自己能调用,现在谁都可以用

    例子全局区:
    无标题.png
    char pMem1()
    {
    char
    p1 = “123456”;
    return p1;
    }
    char
    pMem2()
    {
    char p2 = “123456”;
    return
    p2;
    }
    int main(void)
    {
    char p1 = NULL;
    char
    p2 = NULL;
    p1 = pMem1();
    p2 = pMem2();

    printf(“p1=%s, p1=%p, &p1=%p\n”, p1, p1, &p1);
    printf(“p2=%s, p2=%p, &p2=%p\n”, p2, p2, &p2);
    system(“pause”);

    return 0;
    }
    //两个不同函数定义一个相同的字符串,内存地址一样。在全局区中
    //两个函数中定义的指针p1的地址是不一样的。在栈区中,函数调用结束释放。
    //%s打印内存地址存储的值。

    例子栈区:
    无标题0.png
    char *p_str()
    {
    char str[100]=”123”;//指针是4个字节,100个字节的数组是赋值了全局变量的内容,拷贝了一份到栈区和 //地址无关
    return str;
    }

    int main(void)
    {
    char *p = NULL;
    p = p_str();

    //%s打印内存地址所指向内存空间的数据
    printf(“p=%s\n”, p);//p数组的首地址 p打印这个地址所对应的内存空间的值。
    printf(“\n”);
    system(“pause”);

    return 0;
    }

    //p=烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫
    //str的内存空间在栈区已经被释放

    例子堆区:
    无标题0.png
    char phead()
    {
    char
    tmp = (char *)malloc(100);
    if (tmp == NULL)
    {
    return NULL;
    }

    strcpy(tmp, “123”);
    return tmp;
    }

    int main(void)
    {
    char *p = NULL;
    p = phead();

    if (p != NULL)
    {
    printf(“%s\n”, p);
    free(p);
    p = NULL;
    }

    system(“pause”);

    return 0;
    }