码迷,mamicode.com
首页 > 编程语言 > 详细

C语言 内存四区与函数调用模型

时间:2018-03-04 11:48:48      阅读:235      评论:0      收藏:0      [点我收藏+]

标签:又能   理解   ++   转换   debug   程序   右值   def   存储位置   

C语言提高笔记

标签(空格分隔): C++ C语言


day1

数组做函数参数的退回问题

数组做函数参数会退回为一个指针, 正确做法:把数组的内存首地址和数组的有效长度传给被调用函数。
实参的a 和 形参的a 的数据类型本质不一样, 形参中的数组,编译器会把它当成指针处理 只会分配四个字节。
形参写在函数上,和写在函数内是一样的,只不过是具有对外的属性而已.

数据类型本质分析

  1. 数据类型可理解为创建变量的模具(模子);是固定内存大小的别名
  2. 数据类型的作用:编译器预算对象(变量)分配的内存空间大小
  3. b &b 数组数据类型 (1定义一个数组类型 2定义一个数组指针 3数组类型和数组指针类型的关系) ====>压死初学者的三座大山

可以用数组的名字作为指向数组第一个元素的指针。

void main()
{
    int a; //告诉c编译器分配4个字节的内存
    int b[10] ; //告诉c编译器分配40个自己内存

    printf("b:%d, b+1:%d, &b:%d, &b+1:%d \n", b, b+1, &b, &b+1);

    printf("sizeof(b):%d \n", sizeof(b));  //40
    printf("sizeof(a):%d \n ", sizeof(a)); //4
        
    // b+1  &b+1 结果不一样  //b &b所代表的数据类型不一样
    //b 代表的数组首元素的地址
    //&b代表的是整个数组的地址  

    printf("hello....\n");
    system("pause");
}

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

函数也可以看成一种数据类型

变量的本质

既能读又能写的内存对象,称为变量;若一旦初始化后不能修改的对象则称为常量

本质:一段连续内存空间的别名。通过变量来申请和命名内存空间。
三要素: 名称、大小、作用域

指针是内存空间的别名。

程雪内存四区模型

  1. 栈区:由编译器自动分配释放,存放函数的参数值,局部变量的值等;
  2. 堆区:一般由程序员分配释放,若程序员不释放,程序结束时可能由操作系统回收;
  3. 全局区:全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,该区域在程序结束后由操作系统释放;
  4. 常量区:字符串常亮和其他常量的存储位置,程序结束后由操作系统释放;
  5. 程序代码区:存放函数体的二进制代码。
// 全局区的理解
char *getStr1()
{
// 指针指向谁,将将谁的地址赋给地址
// 指针变量与它指向的内存空间变量不同
    char *p1 = "abcdefg2";  //静态变量,全局区
    return p1;
// 函数析构后,p1消失,常量"abcdefg2"不被析构
}
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 \n", p1, p2);

    //打印p1 p2 的值
    printf("p1:%d , p2:%d \n", p1, p2);

    printf("hello...\n");
    system("pause");
    return;
}
// 堆栈区的理解
//堆
char *getMem(int num)
{
    char *p1 = NULL;
    p1 = (char *)malloc(sizeof(char) * num);
    if (p1 == NULL)
    {
        return NULL;
    }
    return p1;
// 函数结束后,p1指向的内存块不会被析构
}

//栈
//注意 return不是把内存块 64个字节给return出来,而是把内存块的首地址(内存的标号0xaa11) ,返回给 tmp

// 理解指针的关键,是内存. 没有内存哪里的指针 
char *getMem2()
{
    char buf[64]; //临时变量 栈区存放
    strcpy(buf, "123456789");
    //printf("buf:%s\n", buf);
    return buf;
}

void main61()
{
    char *tmp = NULL;
    tmp = getMem(10);
    if (tmp == NULL)
    {
        return ;
    }
    strcpy(tmp, "111222"); //向tmp做指向的内存空间中copy数据

    //tmp = getMem2();
    tmp = 0xaa11;

    printf("hello..tmp:%s.\n", tmp);
    system("pause");
    return ;
}
void main()
{
    int a;
    int b ;

    char buf[128];  //静态联邦的时候 buf所代表的内存空间的标号 就已经定义下来了

    printf("&a:%d , &b: %d \n", &a, &b);
    system("pause");
    return ;
}

在release 和debug模式下,栈的开口方向不同,releas模式向上,debug向下,一般认为栈开口向下,不管栈开口向上还是向下,静态联邦的时候 buf所代表的内存空间的标号 就已经定义下来了。

C语言 内存四区与函数调用模型

标签:又能   理解   ++   转换   debug   程序   右值   def   存储位置   

原文地址:https://www.cnblogs.com/zi-wang/p/8503994.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!