数据结构1

内存空间划分

一个进程启动后,系统会为该进程分配4G内存空间。

其中0-3G是用户空间,主要是程序员写代码的操作部分。

3-4G主要是内核空间,主要是底层驱动部分。

其中0-3G的用户空间又划分为栈区,堆区,静态区

静态区又划分为4个段:bss段,data段,ro段,txt段

所有进程共享3-4G的内核空间,每个进程会独立拥有0-3G的用户空间

应用层主要操作0-3G用户空间,底层主要操作3-4G的内核空间

栈区特点

计算机自动申请和释放空

栈区存放数据的特点:先进后出,后进先出(FILO --->first in last out)

先定义的变量后申请内存,后定义的变量先申请内存

例:

int a //最后给a申请变量

int b //再给b申请变量

int c //先给c申请变量

栈区对数据申请空间的先后顺序:从大到小

堆区特点

程序员手动申请和释放空

堆区存放数据的特点:先进先出,后进后出

先定义的变量先申请内存,后定义的变量后申请内存

例:

int *p1=(int *)malloc(sizeof(int)); //先对p1申请内存空间

int *p2=(int *)malloc(sizeof(int)); //后对p2申请内存空间

栈区对数据申请空间的先后顺序:从小到大

动态内存分配和回收(在堆区申请空间,释放空间)

在C语言中使用malloc函数申请堆区空间,使用free函数释放堆区空间

malloc函数

功能:申请堆区空间

格式:

void *malloc(size_t size);

*需要头文件: #include <stdlib.h>

函数返回值:void * ,使用时需要强制转换

函数名:malloc

参数:申请空间的字节大小,必须以字节为单位,可以借助于sizeof()运算符

例:

单个申请:int *p1=(int *)malloc(sizeof(int));--->int *p1=(int *)malloc(4);

连续申请:int *p2=(int *)malloc(sizeof(int)*3);

错误案例:

int *p1=(int *)malloc(int); //不能直接用int

free函数

功能:释放堆区空间

只申请空间但不释放内存会导致内存泄露

在合适的位置释放内存空间即可避免内存泄漏

格式:

free [options]

*需要头文件: #include <stdlib.h>

函数返回值:无viod

函数名:free

参数:要释放的指针(指针存储了堆区空间)

例:

单个释放:free(p1);

连续释放:free(p2);

经过free释放空间后,p1,p2会变为野指针(指向的空间被释放,指向不存在)

例:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
    int* p1=(int *)malloc(sizeof(int));          //在堆区申请列四个字节大小的空间,并将首地址赋值给p1
    printf("%d\n",*p1);
    *p1=100;
    printf("%d\n",*p1);
    int* p2=(int *)malloc(sizeof(int)*5);          //在堆区申请五个四字节大小的空间,并将首地址赋值给p2
    for(int j=0;j<5;j++)
    {
        *(p2+j)=j*2;
    }
    for(int i=0;i<5;i++)
    {
        printf("%d",*(p2+i));
    }
    putchar(10);
    free(p1);
    free(p2);
    //为了避免野指针,要将指针置空
    p1=NULL;
    p2=NULL;
    return 0;
}                                                 
                                                                                                                 

练习:

在堆区空间连续申请5个int类型大小空间,用来存放从终端输入的5个学生成绩,然后显示5个学生成绩,再将学生成绩升序排序,排序后,再次显示学生成绩。显示和排序分别用函数完成

要求:用malloc和free完成

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void fun(int* q)
{
    printf("成绩展示\n");
    for(int i=0;i<5;i++)
    {
        printf("%d ",*(q+i));
    }
    putchar(10);
}
void pai(int *o)
{
    for(int i=1;i<5;i++)
    {
        for (int j=0;j<5-i;j++)
        {
            if (*(o+j)>*(o+j+1))
            {
                int t;
                t=*(o+j);
                *(o+j)=*(o+j+1);
                *(o+j+1)=t;
            }
        }
    }
    printf("排序完展示\n");
    for(int q=0;q<5;q++)
    {
        printf("%d ",*(o+q));
    }
    putchar(10);
}
int main(int argc, const char *argv[])
{
    int num[5];
    printf("输入成绩\n");
    for(int I=0;I<5;I++)
    {
        scanf("%d",&num[I]);
    }
    int* p=(int *)malloc(sizeof(int)*5);          //在堆区申请五个四字节大小的空间,并将地址赋值给p2
    for(int j=0;j<5;j++)
    {
        *(p+j)=num[j];
    }
    fun(p);
    pai(p);
    free(p);
    //为了避免野指针,要将指针置空
    p=NULL;                                                                                                 
    return 0;
}

野指针:

  1. 未初始化的指针
  2. 释放内存后未置空的指
  3. 指向数组的指针,当越界访问时,该指针为野指针
  4. 指针指向函数的返回值(函数调用时,分配空间,函数结束时,释放地址)

值传递,地址传递,值返回,地址返回

左值:既可以放在等号左边,也可以放在等号右边,有地址空间(变量,堆区空间)

右值:只能放在等号右边,没有地址空间(常量,临时值,表达式的运算结果),右值不可改变

值传递:将实参传递给形参的过程,将实参的数据复制一份给形参,所以形参的改变,不影响实参

地址传递:将实参数据的地址传递给形参的过程,形参可以是指针也可以是数组进行接收,所以形参的改变,可以改变实参

值返回:将一个数据返回,该函数的返回值,只能作为右值(值不可改变)

地址返回:将一个数据的地址返回(保证数据的生命周期要足够长),该函数的返回值可以作为左值

const

功能:const修饰的变量为常变量(只读变量),变量值不可变

const修饰的全局变量在静态区的ro段,const修饰的局部变量在栈区

const必须在定义时初始化

const int a=10; ---> int const a=10;

int const*p=&a; //表示指针的指向可以改变,但对应的值不可以改变(指针常量)

int *const p=&a; //表示指针的指向不可改变,但对应的值可以改变(常量指针)

int const * const p=&a; //表示指针的指向及其对应的值均不可改变

错误示范:int *p=&a; //不能直接使用指针指向常变量

类型重定义typedef

功能:给已有的数据类型重新命名,可以使代码简单易懂

格式:

typedef 数据类型 新名; //用新名替换原来的变量名

typedef int A; //普通类型重定义格式

typedef int *D [5]; //构造类型重定义格式

宏定义define

普通宏的定义

  1. #define:固定,预处理命令
  2. 宏名:满足c语言命名规范(由数字,字母,下划线组成;不可以是关键字;不可以是数字开头;见名知意,区分大小写)

一般宏名大写:宏大写,变量小写,函数名驼峰/下划线

宏---MAX 变量---max 函数---Max

  1. 宏体:默认是字符串类型
  2. 宏:只替换不做计算,不做正确性检测
  3. 宏只发生在预处理阶段

带参宏的定义

#define MAX(x,y) x>y?x:y

 练习

在堆区中申请两个长度为32的空间,实现两个字符串的比较(非函数实现)

定义函数,在堆区中申请空间,两个申请,主函数需要调用两次

定义函数,实现字符串的输入

void input(char *p)

调用函数实现字符串比较,在主函数中输出大小

int my_strcmp(const char *s1,const char *s2)

定义函数,释放空间

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *my_apply(int n)
{
    char *p=(char *)malloc(n);
    if(NULL==p)
        return NULL;
    else
        return p;
}
void my_gets(char *p)
{
    gets(p);
}
int my_strcmp(const char *s1,const char *s2)
{
    int i=0;
    while(*(s1+i)==*(s2+i))
    {
        if (0==*(s1+i))
            break;
        i++;
    }
    int sub=*(s1+i)-*(s2+i);
    return sub;
   }
void my_free(char *p)
{
    free(p);
}
int main(int argc, const char *argv[])
{
    char *p1=my_apply(32);
    char *p2=my_apply(32);
    my_gets(p1);
    my_gets(p2);
    int sub=my_strcmp(p1,p2);
    if(sub>0)
        printf("p1>p2\n");
    else if(sub<0)
        printf("p1<p2\n");
    else if(0==sub)
    {
        printf("p1=p2\n");
    }
    my_free(p1);
    my_free(p2);
    return 0;                                                                              
}
  • 25
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值