以下是我上一个问题的内容:基于C指针的可增长堆栈
我已经做了一些改进(希望如此!)基于非常有帮助的意见和建议。我已经检查了堆栈现在可以推送和弹出双倍,所以希望它也能用结构。
对于我所作的改变,我有很多疑问:
memcpy()没有使用void *,所以我转而使用uin8_t;这是推荐的/必要的,还是可以转换为uint8_t for memcpy()?不确定哪种方法是最好的..。malloc()/realloc()?返回错误代码?出口?返回NULL?再次,我非常感谢任何建议/批评:
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
#define MAX_ITEMS 16
typedef struct {
uint8_t *data;
size_t itemSize;
unsigned count;
unsigned capacity;
} Stack;
void stack_init(Stack *stack, size_t itemSize, unsigned capacity);
bool stack_is_empty(const Stack *stack);
void stack_push(Stack *stack, void *item);
void* stack_pop(Stack *stack);
void stack_destroy(Stack *stack);
void stack_init(Stack *stack, size_t itemSize, unsigned capacity)
{
unsigned initialCapacity = capacity == 0 ? 1 : capacity;
size_t size = initialCapacity * itemSize;
stack->count = 0;
stack->capacity = initialCapacity;
stack->itemSize = itemSize;
stack->data = (uint8_t *)malloc(size);
if (stack->data == NULL)
{
// TODO
}
memset(stack->data, 0, size);
}
bool stack_is_empty(const Stack *stack)
{
return stack->count == 0;
}
void stack_push(Stack *stack, void *item)
{
if (stack->count >= stack->capacity)
{
stack->capacity *= 2;
stack->data = (uint8_t *)realloc(stack->data, stack->capacity * stack->itemSize);
if (stack->data == NULL)
{
// TODO
}
}
unsigned offset = stack->count * stack->itemSize;
memcpy(stack->data + offset, item, stack->itemSize);
stack->count++;
}
void* stack_pop(Stack *stack)
{
if (stack_is_empty(stack) == true)
{
// TODO
}
uint8_t *item = (uint8_t *)malloc(stack->itemSize);
if (item == NULL)
{
// TODO
}
stack->count--;
unsigned offset = stack->count * stack->itemSize;
memcpy(item, stack->data + offset, stack->itemSize);
return (void *)item;
}
void stack_destroy(Stack *stack)
{
free(stack->data);
stack->count = 0;
}
int main(void)
{
Stack stack;
stack_init(&stack, sizeof(int), 0);
for (int i = 0; i < MAX_ITEMS; i++)
{
stack_push(&stack, (void *)&i);
}
while (!stack_is_empty(&stack))
{
int value;
value = *((int *)stack_pop(&stack));
printf("%d\n", value);
}
stack_destroy(&stack);
}发布于 2020-03-04 18:49:28
stack->data = (uint8\_t \*)realloc(stack->data, stack->capacity \* stack->itemSize);
这是错误的,因为如果realloc()失败了,那么现在就没有办法访问stack->data以前指出的内存了。realloc()的正确模式是:
void *newData = realloc(stack->data, stack->capacity * stack->itemSize);
if (!newData) {
// Insert error handling - you'll want to restore the old stack->capacity here
// or (better) wait until we're okay before updating.
return FAILURE:
}
stack->data = newData;我建议在分配时不要转换malloc()家族的结果--这些函数返回void*,它可以分配给没有强制转换的任何指针类型。不必要的强制转换只会分散读者的注意力(因为强制转换通常表示代码中的危险区域)。从指针类型到void*的转换也是如此,如下所示:
退回(无效*)项目;
那很简单
return item;stack_pop接口很难使用-调用者必须处理可能的空指针返回,并且必须记住free()结果。相反,考虑让调用方提供要写入的内存:
void stack_pop(Stack *stack, void *target);调用方应该已经知道了target所需的大小,现在可以在本地(auto)存储中获得结果:
int foo;
stack_pop(&stack, &foo);
// no need to check for null, or to call free()https://codereview.stackexchange.com/questions/238380
复制相似问题