C 入门 第十节 存储区

int b = 5; // 存放在静态区 作用域是所有文件
//  代码区
void testMemory()
{
    printf("代码区 ");
}
//static int b1 = 8; //作用域所有文件
int main(int argc, const char * argv[]) {
/*
    在计算机的内存中,可以分为5个区,每个区都有各自的操作以及管理内存的方式
    栈,堆,静态(全局),常量,代码区是按照内存笛子从小到大分配的
    代码区;

//   打印各个存储区区域
//    栈区:
    int a = 3;
//    堆区:
    int *p = malloc(10);
//    静态(全局):
    static int b = 5;
//    常量:
    char *s = "iphone";
//    函数存储在代码区:
    printf("栈区:%p ",&a);
    printf("堆区:%p ",p);
    printf("静态:%p ",&b);
    printf("常量:%p ",s);
    printf("代码:%p ",testMemory);
*/
#pragma mark -----------栈区:函数参数或者是局部变量存储的区域----------
/*
 
    栈区内存
    1 . 局部变量的存储空间,基本都在栈区,局部变量在函数,循环,分支中定义.
    2 . 栈区的存储空由高到低分配,从低到高存储.
    3 . 栈区内存由系统负责分配和回收,开发者没有管理的权限.定义局部变量时由系统分配存储空间,局部变量被销毁时由系统回收存储空间,但是存储空间中的数据没有被清空
    4 . 当函数,循环,分支执行结束后,局部变量的生命周期结束,不能在被使用,由系统销毁并回收存储空间.
    5 . 栈底,栈顶. 栈底是栈区的起始位置,先定义的变量所占用的内存从靠近栈底开始分配;后定义的变量所占的内存逐渐向栈顶分配.
    6 . 入栈,出栈. 入栈: 定义新的局部变量,分配存储空间;出栈: 局部变量被销毁,存储空间被收回
    7 . 栈的特点: 先进后出,后进先出;
    8 . 栈区会存在安全问题: 在函数中返回栈内存是不安全的
*/
    
//    int a = 10;
//    char b = 'a';
//    double c = 3.4;
//    printf("a的地址: %p ",&a);
//    printf("b的地址: %p ",&b);
//    printf("c的地址: %p ",&c);
//
    
/*
    常量区
    1 . 常量存储在常量区. 常量 字符串等等
    2 . 常量区存储空间是由系统分配和回收
    3 . 程序运行结束后,常量区的存储空间被收回
    4 . 常量区的数据只能被读取,不能被修改.修改会造成崩溃
*/
 
#pragma mark -------静态区: 全局变量和静态变量存储的区域-----------
/*
    静态区
    1. 全局变量,使用static修饰的局部变量,都存储在静态区.
    2. 静态区的存储空间由系统分配和回收.
    3. 程序运行结束后,静态区的存储空间被回收.静态区变量的生命周期跟程序一样长.
    4. 静态变量只能初始化一次,在编译时进行初始化,运行期可以修改
    5. 静态变量如果没有实质初始化,默认值为0;
*/
//    static int b1 = 8; //静态变量,作用域是本文件
    
#pragma mark  ---------代码区: 所有语句编译的cpu指令存储的区域--------------------
/*
    代码区
    1. 由系统分配和回收
    2. 程序结束后,由系统回收分配过的存储空间
    3. 只能读,不能改
*/
 
#pragma mark ---堆区: 由我们(ios开发工程师)自主管理的区域(手动开辟,手动释放)--------
/*
    堆区
    1. 由开发者负责分配和回收
    2. 忘记回收内存会造成内存泄露
    3. 程序结束后会回收堆区内存,但是如果不能及时回收堆内存,程序运行期间可能会因为内存泄露造成堆内存被全部占用,程序无法运行.

 
    内存分配函数
    void *malloc(size)
    void * 表示的是无类型指针,可以转换任意类型指针.
    函数的作用: 在对区开辟指定size个字节的空间,并把空间的首地址返回

    int *p = NULL;
    p = malloc(sizeof(int));
    *p = 4;
    printf("%d ",*p);
    
    
    float *r = NULL;
    r = malloc(sizeof(float));
    *r = 8;
    printf("%.2f ",*r);

 //  分配存储空间存储数组元素,即分配多个连续的存储空间
    
 //  练习: 分配1个字符数组的内存,8个元素 "iPhone"
    char *p = malloc(sizeof(char) * 8);
    strcpy(p, "iphone");
    printf("%s ",p);

    
//  练习: 分配一个整型的数组,10个元素,随机产生10个30~60之间的数,存储在分配的内存空间
    int *p = malloc(sizeof(int) *10);
    for (int i = 0; i < 10; i ++)
    {
        *(p+i) = arc4random()%(60 - 30 + 1) + 30;
    }
    
    for (int i = 0; i < 10; i ++)
    {
        printf("%d ",*(p+i));
    }
    printf(" ");

    
    
    typedef struct student
    {
        char name[20];
        int age;
    }Student;
    Student *p12 = malloc(sizeof(Student));
    strcpy(p12 -> name, "zhangsan");
    p12 -> age = 18;
    printf("%s %d ",p12 ->name,p12 -> age);
    
  释放开辟的空间
//  void free(void *); 将指定的地址所对应的空间释放

    
    int *r = NULL;
    r = malloc(sizeof(int)); //这一块开辟的内存找不到,造成内存泄露
    r = malloc(sizeof(int));
    *r = 10;
    free(r); //开辟空间记得区释放,如果不释放,会出现内存问题:内存泄露
    
    r = NULL; //当空间回收之后,将指针置为null 安全,避免出现野指针,野指针: 指针指向不属于自己控制的存储单元
    free(r); //内存问题: 过度释放

//  void *calloc(int n,size_t size);  在堆区开辟n*size个字节空间,并把空间地址返回,该函数会将空间进行清0操作,在效率上比malloc低
    
    char *str = NULL;
    str = (char*)calloc(10, sizeof(char));
    strcpy(str, "hello");
    printf("string is : %s ",str);
    free(str);
    str = NULL;
 */
/*
    void *realloc(void*p,size_t newSize ); //在给定的地址空间上,如果当前指针空间足够,那么将他地址扩大,如果空间不足,那么重新找一块新的地址按照newSize大小分配空间.将原有数据从头到尾拷贝到新分配的内存区域,然后自动释放原来指针指向的内存区域,不需要free
    int *p_old = malloc(10);
    int *p_new = realloc(p_old, 150);
    printf("%p %p ",p_old,p_new);
//  如果返回的地址和新地址不一样,那么系统会将原来的地址进行一次free,对于realloc()操作,只需要释放我们新的地址空间即可
 //   free(p_old);//过度释放
    free(p_new);
 
//   void *memset(void *p,int c,size_t size) 从给定的地址开始size个字节直接重置为c,注意:该函数以字节单位进行操作.注要作用于清0.
 
    for (int i = 0; i < 3; i ++)
    {
        array[i] = i;
        printf("%d ",array[i]);
    }
    //全置为0
    memset(array, 0, 12);
    printf(" ");
    for (int i = 0; i < 3; i ++)
    {
        printf("%d ",array[i]);
    }
    printf(" ");
    char *p11 = malloc(10);
    memset(p11, 'a', 10);
    for (int i = 0; i < 10; i ++)
    {
        printf("%c ",p11[i]);
        
    }
    printf(" ");

//  int memcmp(void *p,void *q,size_t Count); 从给定的俩个地址p和q开始比较count个字节,返回第一个不相等字节空间的差值
    int num1[3] = {1,2,3};
    int num2[3] = {1,2,2};
    int result = memcmp(num1, num2, 9);  // 9 : 比较的字节数
    printf("%d ",result);
 */
//  void *memcpy(void *p, void *q, size_t n); 从指定的scorce指向的地址向dest指向的地址单元拷贝n个字节
    char wrongName[] = "bjs141148";
    char rightName[] = "15";
    memcpy(wrongName, "B", 1);
    memcpy(wrongName + 3, rightName, 2);
    printf("%s ",wrongName);

原文地址:https://www.cnblogs.com/wangshuai-1129/p/5079090.html