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

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所代表的内存空间的标号 就已经定义下来了。

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

时间: 2024-08-26 22:58:50

C语言 内存四区与函数调用模型的相关文章

C语言提高之技术模型层次、学习标准、特点、内存四区、函数调用模型

1.C语言技术模型分层: 其中,接口的封装和设计尤为重要! 2.着重需要培养的能力 (1)接口的封装和设计(业务模型的抽象.功能抽象和封装) ---重中之重! a.接口api的使用能力: b.接口api的查找能力(快速上手): c.接口api的实现能力: // SOCKETCLIENT_H,一个简单信息系统的封装接口 #ifndef _SOCKETCLIENT_H #endif _SOCKETCLIENT_H #ifdef __cplusplus extern "C" { #endif

c语言内存四区模型

c语言内存四区模型:代码区,全局区(常量区),栈区,堆区 在全局区(常量区),两个字符串完全一样c++编译器只会定义一份 char * getBuf() { char buf[20]; strcpy(buf, "abcde"); return buf; } abcdX?  有乱码! 确实把内存地址返回了,但不能用 被调函数调用完毕,在临时区分配的内存统统消失 char *buf= (char *)malloc(sizeof(char)*20); 手动malloc申请一份内存,由程序员手

C语言内存四区的学习总结(二)---- 堆区

接上篇,内存四区的分析-静态区,下面来说明一下堆区总结. 堆区分析: 堆区(heap):一般由程序员分配释放(动态内存申请与释放),若程序员不释放,程序结束时可能由操作系统回 就下面的程序: #include "stdio.h" #include "string.h" char *getMem(int size) { char *p = NULL; p = (char *)malloc(sizeof(char) * size); if(p == NULL) retu

C语言内存四区

按照老版操作系统来学习,内存对于程序来讲分四区.分别是 代码区,静态区,栈,堆. 由上面程序执行的结果可知: 貌似结果就是 静态代码堆栈 静态区存放的是程序中所有静态变量和常量的值.静态区的大小是程序加载到内存之后就固定的,不会再发生改变. 代码区中存放的是程序中的代码,不能修改它的值,只能通过指针或者变量名来使用函数.[当然强行修改是被允许的但是可能发生未知错误.] 堆是一块很大的区域,通常情况下是4G的大小,(这个数字通常情况下是虚拟的,但是可以利用现代操作系统来利用硬盘模拟出来这么一块儿空

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

首先是操作系统将代码程序加载到内存中 然后将内存分为4个区 栈区,程序的局部变量区,函数传递的参数,由编译器自动进行内存资源的释放. 堆区,动态内存申请,如果不手动释放内存,则这块内存不会进行析构. 全局区,静态区,常量区(字符串存放的位置),程序结束后,有操作系统释放 代码区,存放函数体的二进制代码. 最后,操作系统找到main函数的入口,就开始代码的执行. 一般内存四区中的栈的开口方向是向下的.为什么要这样设计呢,因为设计栈的方向向下,可以给应用程序设定栈的大小,这样就可以避免栈溢出. 不管

内存四区模型与指针

数据类型的封装 1.void的字面意思是"无类型",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

内存四区模型

注:一个程序只建立一个内存四区,所有函数共用这个内存四区. 内存四区如下: 一.全局区 全局变量和静态变量的存储是放在一起的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域, 该区域在程序结束后由操作系统释放: 常量区——字符串常量和其他常量的存储位置,程序结束后由操作系统释放. 在代码运行期间,C编译器会做优化处理, 1).当定义两个不同字符串时,全局区会开辟两个内存空间存放字符串, 2).当定义两个相同的字符串时,全局区只开辟一个内存空间,变

面向过程—面向对象(C++的封装,this)_内存四区_变量生命周期

1.面向对象主要涉及  构造函数.析构函数.虚函数.继承.多态等. 2.对各种支持 的底层实现机制 c语言中,数据 和 处理数据的操作(函数) 是分开来声明,即语言本身并没有支持 “数据和函数”的关联性. 在C++中,通过抽象数据类型(abstract data type, ADT),在类中定义数据和函数,来实现数据和函数直接的绑定. C++成员数据:static.nonstatic C++成员函数:static.nonstatic.virtual C++中的类class从面向对象理论出发,将变

深入理解数据类型、变量类型属性、内存四区和指针

数据类型可理解为创建变量的模具(模子):是固定内存大小的别名. 数据类型的作用:编译器预算对象(变量)分配的内存空间大小. 既能读又能写的内存对象,称为变量:若一旦初始化后不能修改的对象则称为常量. 变量本质:(一段连续)内存空间的别名. 内存四区 栈区(stack):也叫临时区,由编译器自动分配释放,存放函数的参数值,局部变量的值等. 堆区(heap):一般由程序员分配释放(动态内存申请与释放),若程序员不释放,程序结束时可能由操作系统回收. 全局区(静态区)(static):全局变量和静态变