使用 void 指针在 C 中重新编程 Calloc / Realloc
Reprogramming Calloc / Realloc in C Using void pointers
我实际上是在学习 C 编程,而我的学校实际上不允许我们在不重新编程的情况下使用 calloc / realloc。这就是我寻求帮助的原因。
这是我的问题:
我想使用 void *
使我的代码可重用,但是当我尝试 运行 通过我的数组时遇到问题 "dereferencing void *
pointer"。我无法获取最终指针的类型。
这是我的功能:
#include <stdlib.h>
void *my_calloc(size_t size, size_t n) //n = number of bytes your type : sizeof(<whatever>)
{
void *ptr = NULL;
if (size < 1 || n < 1)
return (NULL);
ptr = malloc(n * (size + 1));
if (ptr == NULL)
return (NULL);
for (int i = 0; i != (n * (size + 1)); i++) {
*ptr = NULL; //Here is my problem
ptr++;
}
return (ptr);
}
void *my_realloc(void *src, size_t size, size_t n)
{
void *dst = NULL;
int dst_len = 0;
if (src == NULL || size < 0 || n < 1)
return (NULL);
dst_len = my_strlen(src) + size;
if (dst_len == my_strlen(src))
return (src);
dst = my_calloc(dst_len, n);
if (dst == NULL)
return (NULL);
for (int i = 0; src[i] != NULL;i++)
dst[i] = src[i]; //Here is the same problem...
free(src);
return (dst);
}
我在编写 post 时发现了一个问题,我的 my_strlen
函数只能接受一个字符 *...所以我需要一个看起来像 my_strlen
的函数:
int my_strlen(void *str)
{
int len = 0;
while (str[len] != NULL) { //same problem again...
len++;
}
return (len);
}
我调用 calloc / malloc 的典型函数是:
int main(void)
{
char *foo = NULL;
int size = 0;
int size_to_add = 0;
size = <any size>;
//free(foo); //only if foo has been malloc before
foo = my_calloc(size, typeof(*foo));
//something
size_to_add = <any size>;
foo = my_realloc(foo, size_to_add, sizeof(*foo))
//something
free(foo);
return (0);
}
感谢您的帮助。
void
是一个不完整的类型,因此您不能取消引用 void *
。但是,您可以将其转换为 char *
或 unsigned char *
以访问单个字节。
所以my_calloc
可以这样做:
((char *)ptr)[i] = 0;
而my_realloc
可以做到这一点:
((char *)dst)[i] = ((char *)src)[i];
my_calloc()
有各种烦恼:
尝试在 void *
上进行指针数学运算
这是未定义的行为 (UB)。
而是使 ptr
成为字符指针。
// void *ptr = NULL;
unsigned char *ptr = NULL;
...
ptr++;
尝试取消引用 void *
这也是UB
而是使 ptr
成为字符指针。
// void *ptr = NULL;
unsigned char *ptr = NULL;
...
// *ptr = NULL;
*ptr = '[=11=]';
my_calloc()
比 calloc()
分配更多的内存
与calloc()
相同,不加一个。
// ptr = malloc(n * (size + 1));
ptr = malloc(n * size);
无溢出保护
my_calloc()
未检测到 n * (size + 1)
的溢出。一个测试是
// Note: it is known n > 0 at this point
if (SIZE_MAX/n > size+1) return NULL;
// or if OP drop the + 1 idea,
if (SIZE_MAX/n > size) return NULL;
my_realloc()
有各种烦恼:
签名不同
我希望 "school actually doesn't allow us to use calloc / realloc without reprogramming them" 的目标是创建一个 realloc()
的替代品,而 my_realloc()
不是。如果需要不同的功能,请考虑一个新名称
void *my_realloc(void *src, size_t size, size_t n)
// does not match
void *realloc(void *ptr, size_t size);
无法处理缩减分配
数据的复制没有考虑到新的分配可能比之前的分配小。这导致 UB。
不需要的代码
size < 0
总是假的
内存泄漏
下面的代码在返回前不会释放 src
。此外,它在 n>0
时不分配任何东西。这不同于 calloc(pit, 0)
和 calloc(NULL, 42)
。
// missing free, no allocation
if (src == NULL || size < 0 || n < 1) {
return (NULL);
}
假设字符串
my_strlen(src)
假设 src
指向一个有效的字符串。 calloc()
不假设。
我实际上是在学习 C 编程,而我的学校实际上不允许我们在不重新编程的情况下使用 calloc / realloc。这就是我寻求帮助的原因。
这是我的问题:
我想使用 void *
使我的代码可重用,但是当我尝试 运行 通过我的数组时遇到问题 "dereferencing void *
pointer"。我无法获取最终指针的类型。
这是我的功能:
#include <stdlib.h>
void *my_calloc(size_t size, size_t n) //n = number of bytes your type : sizeof(<whatever>)
{
void *ptr = NULL;
if (size < 1 || n < 1)
return (NULL);
ptr = malloc(n * (size + 1));
if (ptr == NULL)
return (NULL);
for (int i = 0; i != (n * (size + 1)); i++) {
*ptr = NULL; //Here is my problem
ptr++;
}
return (ptr);
}
void *my_realloc(void *src, size_t size, size_t n)
{
void *dst = NULL;
int dst_len = 0;
if (src == NULL || size < 0 || n < 1)
return (NULL);
dst_len = my_strlen(src) + size;
if (dst_len == my_strlen(src))
return (src);
dst = my_calloc(dst_len, n);
if (dst == NULL)
return (NULL);
for (int i = 0; src[i] != NULL;i++)
dst[i] = src[i]; //Here is the same problem...
free(src);
return (dst);
}
我在编写 post 时发现了一个问题,我的 my_strlen
函数只能接受一个字符 *...所以我需要一个看起来像 my_strlen
的函数:
int my_strlen(void *str)
{
int len = 0;
while (str[len] != NULL) { //same problem again...
len++;
}
return (len);
}
我调用 calloc / malloc 的典型函数是:
int main(void)
{
char *foo = NULL;
int size = 0;
int size_to_add = 0;
size = <any size>;
//free(foo); //only if foo has been malloc before
foo = my_calloc(size, typeof(*foo));
//something
size_to_add = <any size>;
foo = my_realloc(foo, size_to_add, sizeof(*foo))
//something
free(foo);
return (0);
}
感谢您的帮助。
void
是一个不完整的类型,因此您不能取消引用 void *
。但是,您可以将其转换为 char *
或 unsigned char *
以访问单个字节。
所以my_calloc
可以这样做:
((char *)ptr)[i] = 0;
而my_realloc
可以做到这一点:
((char *)dst)[i] = ((char *)src)[i];
my_calloc()
有各种烦恼:
尝试在 void *
这是未定义的行为 (UB)。
而是使 ptr
成为字符指针。
// void *ptr = NULL;
unsigned char *ptr = NULL;
...
ptr++;
尝试取消引用 void *
这也是UB
而是使 ptr
成为字符指针。
// void *ptr = NULL;
unsigned char *ptr = NULL;
...
// *ptr = NULL;
*ptr = '[=11=]';
my_calloc()
比 calloc()
与calloc()
相同,不加一个。
// ptr = malloc(n * (size + 1));
ptr = malloc(n * size);
无溢出保护
my_calloc()
未检测到 n * (size + 1)
的溢出。一个测试是
// Note: it is known n > 0 at this point
if (SIZE_MAX/n > size+1) return NULL;
// or if OP drop the + 1 idea,
if (SIZE_MAX/n > size) return NULL;
my_realloc()
有各种烦恼:
签名不同
我希望 "school actually doesn't allow us to use calloc / realloc without reprogramming them" 的目标是创建一个 realloc()
的替代品,而 my_realloc()
不是。如果需要不同的功能,请考虑一个新名称
void *my_realloc(void *src, size_t size, size_t n)
// does not match
void *realloc(void *ptr, size_t size);
无法处理缩减分配
数据的复制没有考虑到新的分配可能比之前的分配小。这导致 UB。
不需要的代码
size < 0
总是假的
内存泄漏
下面的代码在返回前不会释放 src
。此外,它在 n>0
时不分配任何东西。这不同于 calloc(pit, 0)
和 calloc(NULL, 42)
。
// missing free, no allocation
if (src == NULL || size < 0 || n < 1) {
return (NULL);
}
假设字符串
my_strlen(src)
假设 src
指向一个有效的字符串。 calloc()
不假设。