c/c++

c进阶-内存四驱模型

2018-09-19  本文已影响5人  Peakmain

数组参数传递

代码如下

void print(int arr[]){
    //获取数组的大小
     int length=sizeof(arr)/sizeof(int);
    printf("length=%d\n", length);
    for (int i = 0; i<length; i++){
        printf("%d\n", arr[i]);
    }
}
void main(){
    int arr[] = { 1, 2, 3, 4, 5, 6 };
    //求数组的大小
    int size = sizeof(arr) / sizeof(int);
    printf("size=%d\n", size);
     print(arr);
    getchar();
}

情况分析:我们会发现数组作为参数传递的时候获取不到长度,这是为什么呢?这是因为c/c++编译器会将数组作为参数传递,会退化成一个指针,传的实际是首地址。那如果非要数组作为参数传递怎么解决呢呢?,将数组大小传递过去就可以了

void print(int arr[],int length){
    //获取数组的大小
    /* int length=sizeof(arr)/sizeof(int);*/
    printf("length=%d\n", length);
    for (int i = 0; i<length; i++){
        printf("%d\n", arr[i]);
    }
}
void main(){
    int arr[] = { 1, 2, 3, 4, 5, 6 };
    //求数组的大小
    int size = sizeof(arr) / sizeof(int);
    printf("size=%d\n", size);
    //数组作为参数传递的时候为什么获取不到长度
    //数组作为参数传递,会退化成一个指针,传的实际是首地址
    // print(arr);
    print(arr, size);
    getchar();
}

数据类型的本质

数据类型本质:内存上一块连续的固定大小空间
void*代表任意数据类型的指针

    int a;//告诉c/c++编译器开辟一块连续大小的4字节的内存空间
    int arr[] = {1, 2, 3, 4, 5, 6};//数据类型的内存空间
    a=10;
    //488, 492, 488 ,512      512=488+4*6==&arr+1   如果是 &arr+2  488+4*6*2
    printf("%d, %d, %d ,%d", arr, arr+1, &arr, &arr+1);
    getchar();

变量的本质

固定内存空间大小(一块连续大小的内存空间)的别名,通过变量可以去操作一块内存上的数据
变量的三要素:内存大小,名称,作用域

内存四驱模型

程序运行的流程

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

四驱模型

1.栈区:由编译器自动分配的,存放一些局部变量值和函数,这个里面内存是自动进行回收的
2.堆区:一般都是我们自己开辟的,这个里面的内存需要手动进行释放 malloc->free ,new->delete
3.全局区(静态区):静态的一些常量,字符串等等.
4.程序代码区:存放的是函数的二进制代码

案例:

char* getStrl(){
    //全局区
    char *str="12345";
    return str;
}
char* getStr2(){
    //全局区
    char *str="12345";
    return str;
}
char *getStr3(){
    //栈区最后会释放内存
    char buff[128];
    strcpy(buff,"12345");
    return buff;
}
char* getStr4(){
    // char* buff  char* 是4字节的数据类型,存的是堆区开辟的 128 个字节的首地址
    char* buff = malloc(128);
    strcpy(buff, "12345");
    return buff;
}
void main(){
    char *str1=NULL;
    char *str2=NULL;
    char *str3=NULL;
    str1=getStrl();
    str2=getStr2();
    str3=getStr3();
    char* str4 = getStr4();
    printf("%d , %d, %s, %s",str1,str2,str3,str4);
    getchar();
}

栈的开口方向

    int a = 10;
    int b = 10;
    // buffer 数据类型跟栈的开口方向无关(都是向上)
    char buff[10];
    // buff+1 > buff
    //0508 0496 a的地址要大于b的地址 Debug 开口向下 a>b
    //016 020 b的地址要大于a的地址 Release 开口向上 b>a
    printf("%p , %p, %p, %p", &a, &b, buff, buff + 1);
    getchar();
指针强化:指针也是一种数据类型,虽说都是占用4个字节,但是有数据类型,指针存放的是一块内存地址
    int a=100;
    int* ff = &a;// 虽说是 a 的地址,但是我也可以把 ff 看做一个数组
    ff+=1;

最后我们在举个例子分析下内存四驱模型

#include <stdio.h>
void change(int number){//不能修改
    number = 300;
    printf("%p\n", &number);
}
void change2(int* number){//可以修改
    *number = 300;
    printf("%p\n", &number);
}
void main(){
    int a = 100;
    printf("%p\n", &a);//0031F84C
    //修改a的值
    a = 200;
    change(a);//a变量的值赋值给number变量,number是在另一个函数中,number是一个新的变量
    printf("a==%d", a);//a=200
    change2(&a);//a变量的地址赋值给number变量,number是在另一个函数中,number是一个新的变量
    printf("a==%d", a);//a=300
}

上面我们可以知道change(a)的时候并没有修改a的值,这是为什么呢?但是我们调用change2(&a)的时候又改变了a的值,这又是为什么呢?


change.png

我们会发现无论你number修改成什么值,a是不会改变


change2.png
我们可以发现当number此时指向的a的地址,即当number修改了值,会改变赋值给它地址的a的值
上一篇下一篇

猜你喜欢

热点阅读