zoukankan      html  css  js  c++  java
  • C_深入(内存模型)

    01 数据类型:

    为什么有数据类型?
    现实生活中的数据太多而且大小形态不一。
    数据类型与内存的关系:
    数据类型的本质:创建变量的模具,是固定大小的别名。

    #include "stdio.h"
    #include "stdlib.h"
    #include "string.h"
    int main() {
        int a;
        int b[10];
        printf("b:%d,b+1:%d,&b:%d,&b+1:%d 
    ",b,b+1,&b,&b+1);
        //b:6422152,b+1:6422156,&b:6422152,&b+1:6422192
        system("pause");
    }
    

    问题:b,&b所代表的数据类型不一样:
    b代表的是数组首元素的地址,&b代表的是整个数组的地址。&b+1,相当于给整个数组加了1个数组大小的地址。
    重点:(数组数据类型:1.定义;2.数组指针;3.数组类型和数组指针类型的关系)
    数组的大小:

    printf("sizeof(b):%d",sizeof(b));//40
    printf("sizeof(a):%d",sizeof(a));//4
    

    数据类型的作用:编译器预算对象分配的内存空间大小。
    数据类型的别名:typedef

    struct Teacher{
        char name[30];
        int age;
    }
    
    
    main:
    struct Teacher t1;//没有struct关键字会报错
    t1.age = 3;
    

    自定义数据类型:typedef

    typedef struct Teacher{
        char name[20];
        int age;
    }Teacher;
    
    main:
        struct Teacher t1;//没有struct关键字不会报错 
        t1.age = 31;
    

    c语言中会报错,c++中增强了struct关键字。会没有问题。

    数据类型的封装

    1.void"无类型",void*"无类型指针",可以指向任何类型的数据。
    2.用法:

    1.数据类型的封装
    int InitHardEnv(void **handle);
    典型的如内存操作函数memcpy和memset的函数原型分别为   void * memcpy(void *dest, const void *src, size_t len);
      void * memset ( void * buffer, int c, size_t num );
    2.void修饰函数返回值和参数,仅表示无。
    如果函数没有返回值,那么应该将其声明为void型
    如果函数没有参数,应该声明其参数为void
    int function(void) {
    return 1;
    }

    3.void指针的含义:
    C语言规定只有相同类型的指针才可以相互赋值
    void指针作为左值用于“接收”任意类型的指针
    void
    指针作为右值赋值给其它指针时需要强制类型转换

          int *p1 = NULL;
          char *p2 = (char *)malloc(sizoeof(char)*20); 
    

    变量本质分析

    变量概念:即能读又能写的内存对象,若一旦初始化不能修改的对象是常量。
    变量的本质:

    1.程序通过变量名来申请和命名空间
    2.通过变量名访问内存空间(一段连续)内存空间的别名(犹如门牌号)
    3.修改变量的方法:

    1.直接(赋值法)eg:int a = 78;
    2.间接。内存有地址编号,通过地址编号可以修改内存;

    int a;
    int b;
    int *p;
    a = 10;//直接修改
    printf("&a:%d
    ",&a);//获取到a的地址1245024
    //间接修改====直接通过内存修改
    *((int*)1245024) = 200;//int* 表示类型,*()代表作指针
    printf("a:%d
    ",a);//200
    {
        p = 1245024;
        *p = 300;//间接赋值 通过指针修改
    }
    printf("a:%d
    ",a);//300
    

    4.对内存空间能取别名.....
    5.数据类型和变量的关系:通过数据类型定义变量

    总结:

    1.对内存,可读可写;
    2.通过变量往内存读写数据;
    3.不是向变量读写数据,而是向变量所代表的内存空间中写数据。(变量跑哪去了?变量有变量的存储空间);

    思考1:变量三要素(名称、大小、作用域),变量的生命周期?
    思考2:C++编译器是如何管理函数1,函数2变量之间的关系的?

    程序内存四区模型

    内存四区的流程:

    硬盘(程序)>>内存(代码,操作系统代码)=>>执行过程中,C程序内存管理(堆区,栈区,全局区,代码区)
    流程说明:

    1.操作系统把物理硬盘代码load到内存
    2.操作系统把c代码分成四个区
    3.操作系统找到main函数入口执行

    各区元素分析:
    1.栈区(stack):由编译系统自动分配释放,存放函数的参数值,局部变量的值等。
    2.堆区(heap):一般由程序员分配释放(动态内存申请与释放)如程序员不释放,程序结束时可能操作系统回收。
    3.全局区(静态区)(static):如果存储的值一样,c++编译器会自动保留一份。

    1.全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,该区域在程序结束后有操作系统释放。
    2.常量区:字符串常量和其他常量的存储位置,程序结束后有操作系统释放。

    4.程序代码区:存放函数的二进制代码。

    #define  _CRT_SECURE_NO_WARNINGS 
    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>
    
    char *getStr1()
    {
    	char *p1 = "abcdefg2";
    	return p1;
    }
    char *getStr2()
    {
    	char *p2 = "abcdefg2";
    	return p2;
    }
    
    void main()
    {
    	char *p1 = NULL;
    	char *p2 = NULL;
    	p1 = getStr1();
    	p2 = getStr2();
    
    	//打印p1 p2 所指向内存空间的数据
    	printf("p1:%s , p2:%s 
    ", p1, p2);
    
    	//打印p1 p2 的值
    	printf("p1:%d , p2:%d 
    ", p1, p2);//竟然是相等的
    
    	printf("hello...
    ");
    	system("pause");
    	return ;
    }
    
  • 相关阅读:
    从0开始学Swift笔记整理(二)
    从0开始学Swift笔记整理(一)
    JAVA反射机制
    Spring基础知识汇总
    关于类和对象的进一步讨论 C++
    C++ 共用体 枚举类型 所有
    自定义数据类型 C++ 结构体类型 共同体类型 枚举类型 类类型{}
    C++ 指针 引用 变量引用
    函数和指针 C++
    C++字符串与指针 所有的内容也就这么多了。
  • 原文地址:https://www.cnblogs.com/intelwisd/p/8099541.html
Copyright © 2011-2022 走看看