realloc函数返回的是void*类型的指针,指向在堆区重新开辟的内存块的起始地址,memblock是先前开辟的内存块的指针(也就是malloc或calloc之前申请的那块内存空间,即需要调整大小的内存空间),size_t size指的是New size in bytes,新的字节数,注意不是增加的字节数,而是新开辟的那块内存空间的字节数,返回值为调整之后的内存的起始地址。
1.如果p指向的空间之后有足够的空间可以追加,则直接追加,返回的是p原来的起始地址。
2.如果p指向的空间之后没有足够的空间可以追加,则realloc函数会重新找一个新的内存区域,重新开辟一块40个字节的动态内存空间,并且把原来内存空间的数据拷贝回来,释放旧的内存空间还给操作系统,最后返回新开辟的内存空间的起始地址。
3.我们需要用一个新的指针变量来接收realloc的返回值。
4.同时我们要考虑调整内存大小失败的情况,如果开辟失败,我们至少不能让原内存数据失效,我们也要释放原内存数据,并把指针置为空。
5.开辟成功,也不用担心原来的内存有没有浪费,因为realloc函数会把原来的内存空间拷贝回来,再将其内存释放。注意如果ptr!=NULL p=ptr;这个p指针已经被赋为ptr了(就不用考虑原内存空间的指针有没有被置为空指针),所以新空间不再使用时,也要释放内存,并把指针置为空。
1)关于缩容的问题
如果我们realloc的新的内存块的大小<比之前动态内存malloc的大小,可不可以做到缩容来节省空间呢?
它有可能会原地缩容,也有可能会异地缩容。但我们一般不考虑缩容的问题,因为如果系统是异地缩容,它需要找一块空间,把原数据考虑过来,然后再把原空间释放,这样会有性能,时间上的代价。而且如果我们之后又要插入数据,那我们又要进行扩容。
总结一下来说:
缩容:以时间换空间
不缩容:以空间换时间
myfgets
#include <stdio.h>
int my_fgetc(FILE *str) {
char c;
if (fread(&c, sizeof(char), 1, str) == 1) {
return (int)(unsigned char)c;
} else {
return EOF;
}
}
mygets
#include <stdio.h>
char *my_fgets(char *s, int n, FILE *str) {
int i = 0;
char c;
while (i < n - 1 && fread(&c, sizeof(char), 1, str) == 1) {
if (c == '\n') {
break;
}
s[i++] = c;
}
s[i] = '\0';
if (i == 0 && feof(str)) {
return NULL;
}
return s;
}
myfputc
#include <stdio.h>
int my_fputc(int ch, FILE *str) {
unsigned char c = (unsigned char)ch;
return fwrite(&c, sizeof(char), 1, str) == 1 ? ch : EOF;
}
myfputs
#include <stdio.h>
int my_fputs(const char *s, FILE *str) {
int length = 0;
while (s[length] != '\0') {
length++;
}
return fwrite(s, sizeof(char), length, str);
}