用泛型风格在C中实现堆栈

用泛型风格在C中实现堆栈,c,generics,C,Generics,文件栈.h typedef struct { void *elems; int elem_size; int log_len; int alloc_len; void (*free_fn)(void *); } stack; void stack_new(stack *s, int elem_size, void (*free_fn)(void *)); void stack_dispose(stack *s); void stack_push(stac

文件栈.h

typedef struct
{
    void *elems;
    int elem_size;
    int log_len;
    int alloc_len;
    void (*free_fn)(void *);
} stack;

void stack_new(stack *s, int elem_size, void (*free_fn)(void *));
void stack_dispose(stack *s);
void stack_push(stack *s, void *value);
void stack_pop(stack *s, void *address);
以及实现文件stack.c

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define assert(condition) if(!condition) printf("assert fail\n");exit(0) 

void strfree(void *elem);

int main()
{
    stack s;
    int i;
    char *copy, *top;
    const char *friends[] = {"joe", "castiel", "lily"};
    stack_new(&s, sizeof(char *), strfree);
    for(i=0; i<3; i++)
    {
        copy = strdup(friends[i]);
        stack_push(&s, &cp);
    }

    for(i=0; i<=3; i++)
    {
        stack_pop(&s, &top);
        printf("%s\n", top);
    }
    stack_dispose(&s);
    return 1;
}

void strfree(void *elem)
{
    free(*(char **)elem);
}

void stack_new(stack *s, int elem_size, void (*free_fn)(void *))
{
    assert(elem_size > 0);
    s->alloc_len = 4;
    s->free_fn = free_fn;
    s->log_len = 0;
    s->elem_size = elem_size;
    s->elems = malloc(s->alloc_len * s->elem_size);
    assert(s->elems != NULL);
}

void stack_dispose(stack *s)
{
    int i;
    if(s->free_fn)
    {
        for(i=0; i<s->log_len; i++)
        {
            s->free_fn((char *)s->elems + i * s->elem_size);
        }
    }
    free(s->elems);
}

void stack_push(stack *s, void *v)
{
    if(s->log_len == s->alloc_len)
    {
        s->alloc_len *= 2;
        s->elems = realloc(s->elems, s->alloc_len*s->elem_size);
        assert(s->elems != NULL);
    }
    memcpy((char *)s->elems+s->log_len*s->elem_size, v, s->elem_size);
    s->log_len++;
}

void stack_pop(stack *s, void *address)
{
    assert(s->log_len > 0);
    void *source =  (char *)s->elems + (s->log_len - 1) * s->elem_size;
    memcpy(address, source, s->elem_size);
    s->log_len--;
}
  • 它在某个地方坏了,它不会打印出这里定义的三个名称

    const char *friends[] = {"joe", "castiel", "lily"};
    

  • 我知道代码有点太多了,但我真的希望得到一些帮助,我在这里束手无策。

    一个问题是您的
    断言
    宏:

    #define assert(condition) if(!condition) printf("assert fail\n");exit(0) 
    
    退出(0)(再次查看生成的代码)。如果需要断言,请使用标准的
    #include

    您首先发现的问题是:

    assert(s->elems != NULL);
    
    根据定义,这相当于:

    if (!s->elems != NULL)
        printf("assert fail\n");
    exit(0);
    
    !s->elems
    是一个整数,与空指针常量相比为0或1。因此发出警告。编写宏时,请将参数括在括号中。至少:

    #define assert(condition) if(!(condition)){printf("assert fail\n");exit(1);}
    

    这仍然不是一个好的宏,但至少它将消除第一个编译错误,并且当调用它时,
    stack\u new()
    不会因为调用它而退出。请注意,当出现问题时,通常以非零状态退出-以零状态退出表示成功。

    一个问题是您的
    断言
    宏:

    #define assert(condition) if(!condition) printf("assert fail\n");exit(0) 
    
    退出(0)(再次查看生成的代码)。如果需要断言,请使用标准的
    #include

    您首先发现的问题是:

    assert(s->elems != NULL);
    
    根据定义,这相当于:

    if (!s->elems != NULL)
        printf("assert fail\n");
    exit(0);
    
    !s->elems
    是一个整数,与空指针常量相比为0或1。因此发出警告。编写宏时,请将参数括在括号中。至少:

    #define assert(condition) if(!(condition)){printf("assert fail\n");exit(1);}
    

    这仍然不是一个好的宏,但至少它将消除第一个编译错误,并且当调用它时,
    stack\u new()
    不会因为调用它而退出。请注意,当出现问题时,通常以非零状态退出-以零状态退出表示成功。

    使用GDB在调试器中运行代码,以逐行查看它在做什么。谷歌“gdb备忘单”开始使用
    -g

    编译代码,使用gdb在调试器中运行代码,逐行查看它在做什么。谷歌“gdb备忘单”开始使用
    -g

    编译代码谢谢你,因为我没有使用IDE,我忘了我可以调试我的代码谢谢你,因为我没有使用IDE,我忘了我可以调试我的代码