c语言动态内存分配与文件操作

动态内存分配

头文件:<stdlib.h>

1. 内存申请

  1. void* malloc(size_t size)( size:需要申请的内存大小)

#include<stdio.h>
#include<stdlib.h>
#include<string.h>  /*strerror通过标准错误的编号,获得错误的描述字符串,方便用户查找,返回值是指向错误信息的指针。*/
#include<errno.h>   /*errno获取错误内容*/
int main()
{
    int* p = (int*)malloc(10*sizeof(int ));/* void*需要强制类型转换*/
    if (p == NULL)/*(内存可能申请失败)*/
    {
        printf("%s\n", strerror(errno));
    }
    else
    {
        for (int i = 0; i < 10; i++)
        {
            *(p + i) = i;/*!内存申请时p不可以改变,否则p指向的空间无法释放*/
            printf("%d", *(p + i));
        }
    }
    free(p);/*内存释放*/
    p = NULL;/*指针初始化,防止指针对申请的内存破坏.
               同时可避免多次释放的程序错误出现*/
    return 0;
​
}
  1. void * calloc(size_t num,size_t size) (元素数量, 每个元素的大小)

  • 与malloc不同的是calloc会初始化内存为0。

2. 内存调整

void realloc(void ptr,size_t size);(ptr:需要调整的内存地址,size调整后的内存大小)

调整时的注意事项

  1. 原有内存空间之后有足够大的内存空间,则在原来内存空间后面自己追加,原来空间数据不改变

  2. 原有内存空间之后没有足够大的内存空间,则在堆空间找到一个新的空间使用并把原内存复制,释放原来的内存空间,最后返回新内存空间的地址。

  3. 需要用一个新变量接收realloc(否则开辟失败返回的空指针会使指向原来内存空间的指针悬空,即找不到原来申请的内存空间)

c/c++程序中的内存知识 

 

内存泄漏:内存中的数据出现丢失

自定义对齐值#pragma pack(n) #pragma pack()取消自定义对齐值

由于内存对齐以下程序不会崩溃

struct s{
char a[3];
int i
}b;
for(i=0;i<=3;i++)
b.a[i]='a'+i;
因为对齐值为4,因此在定义char a【3】时实际给a分配了四个字节

3内存管理函数

menset(a,5,5*sizeof(int))将a开头5个20个字节设置为5

memcpy(a,5,s)将s开头的5个字节复制到a

memmove(a,5,s)将s开头的5个字节移动到a

memcmp(a,s,5)比较a和s开头的5个字节

memchr(a,ch,5)将a开头的5个字节查找ch第一次出现的位置

4. 动态内存分配应用——柔性数组

特点

  • 结构中的柔性数组成员前面必须至少一个其他成员。

  • sizeof 返回的这种结构大小不包括柔性数组的内存。

  • 包含柔性数组成员的结构用malloc()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小

柔性数组的使用

struct S
{
    int a;
    char arr[];//柔性数组
};
void Test1()
{
​
    //为结构体动态开辟空间,前半部分开的空间大小是4个字节,后半部分是给柔性数组arr开辟的空间
    struct S* ps = (struct S*)malloc(sizeof(struct S) + 100 * sizeof(char));
​
    ps->a = 20;
    strcpy(ps->arr, "abcdefg");
​
    printf("柔性数组:%d\n", ps->a);
    printf("柔性数组:%s\n", ps->arr);
​
    //若是觉得柔性数组开辟100字节不够使用,可以用realloc为其重新开辟空间
    struct S* ptr = (struct S*)realloc(ps, sizeof(struct S) + 200 * sizeof(char));
    if (ptr != NULL)
        ps = ptr;
​
​
    free(ps);
    ps = NULL;  
}
struct B
{
    int a;
    char* arr;
};
void Test2()
{
    //先为结构体B开辟空间,为8个字节
    struct B* ps = (struct B*)malloc(sizeof(struct B));
    //此时为结构体中的指针arr动态开辟空间
    ps->arr = (char*)malloc(sizeof(char)* 100);
​
    ps->a = 20;
    strcpy(ps->arr, "abcdef");
​
    printf("指针:%d\n", ps->a);
    printf("指针:%s\n", ps->arr);
​
    //若是觉得指针指向的空间开辟100字节不够使用,可以用realloc为其重新开辟空间
    char* ptr  = (char*)realloc(ps->arr, 200 * sizeof(char));
    if (ptr != NULL)
        ps->arr = ptr;
​
    free(ps->arr);
    ps->arr = NULL;
    free(ps);
    ps = NULL;
}

开辟数组与开辟指针的区别

柔性数组的优势

  1. 方便内存的释放,只需一次就可以把内存全部释放

  2. 提高访问速度 ,提高内存利用率,相比于指针开辟的空间是连续的,同时减少了内存碎片的产生

文件

文件的打开

1打开文件 FILE *fp=fopen(文件名,使用文件的方式)\隔开目录时要注意用转义字符

2关闭文件 int fclose(文件类型指针)

3键盘---标准输入流:stdin

4屏幕--标准输出流:stdout

文件的定位和监测

文件的定位

1long int a=ftell(文件类型指针)返回检测文件首位置到当前位置的字节数,调用失败时返回-1l

2rewind(文件类型指针)将指针重新定位到文件首

3fseek(文件类型指针,位移量,起始点)

起始点:

  • SEEK_SET 文件首开始

  • SEEK_CUR 文件当前位置

  • SEEK_END 文件尾

文件的检测

1feor(文件类型指针)如果到达文件尾则返回非0否则返回0

2ferror(文件指针)检测文件在输入输出时是否出错,未出错返回0,出错则返回非0

3perror(“1”)打印内容然后打印错误信息

文件的读写

1fgetc(文件类型指针)读取一个字符然后文件后移一个字节 如果读到文件结束符则返回EOF(stdio中的一个符合常量值为-1)

fgec(stdin)==getchar()(返回值为该字符的ASCLL码)

2fputc(字符表达式,文件类型指针)将字符写入文件中,同时文件后移一个字节,写入失败返回EOF

fputc(ch,stdout)==putchar(ch)(返回值为该字符的ASCLL码)

3fscanf(文件类型指针,格式字符串,输入项地址列表)写入失败返回EOF

fscanf(stdin,“%d”,&i)==scanf(“%d”,&i)(返回值为读取数据个数)

4fprintf(文件类型指针,格式字符串,输出项列表)写入失败返回EOF

fprintf(stdout,“%d”,&i)==printf(“%d”,&i)(返回值为读取数据个数)


5fread(a,sizeof(int),10,fp)将fp的文件中读取4*10个字节放于a数组中(读取成功返回值为个数,否则返回0)

6fwrite(b,sizeof(int),6,fp)将b的4*6个字节写入fp的文件中 (写入成功返回值为个数,否则返回0)

7fgets(pstr,n,fp)从fp中读取n-1个字符然后在字符后面加\0,如果遇到换行或文件结束则结束读取,(返回值为pstr首地址否则为NULL)

8fputs(pstr,fp)将pstr写入文件不包括\0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值