【问题标题】:Issue with a generic stack library通用堆栈库的问题
【发布时间】:2014-02-27 10:45:33
【问题描述】:

我正在尝试编写一个通用堆栈库[使用数组],它可以为任何元素大小和元素数量分配一个堆栈。我正在尝试下面的代码。 首先,我收到一条警告,说我在 memcpy 中使用时取消引用 void 指针。

其次,我在尝试打印的输出中遇到了一些问题。请帮忙。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct _stk_
{
    int top;
    int elemsize;
    int numElem;
    void *array;
}stack;

stack *create_stack(int elemsize, int numElem)
{
    stack *stk_handle = malloc(sizeof(stack));

    if(!stk_handle)
    {
        printf("Malloc failed for stack handle\r\n");
        return NULL;
    }
    stk_handle->top = -1;
    stk_handle->elemsize = elemsize;
    stk_handle->numElem = numElem;
    stk_handle->array = calloc(elemsize, numElem);

    if(!(stk_handle->array))
    {
        printf("Malloc failed for stack\r\n");
        free(stk_handle);
        return NULL;
    }

    return stk_handle;
}

void push (stack *stk_handle, void *element)
{
    memcpy(&(stk_handle->array[++stk_handle->top]), element, stk_handle->elemsize);
    printf("Pushed element %s to stack. Top is %d\r\n", element, stk_handle->top);
}

void pop (stack *stk_handle, void *element)
{
    memcpy(element, &(stk_handle->array[stk_handle->top--]), stk_handle->elemsize);
    printf("Popped element %s from stack. Top is %d\r\n", element, stk_handle->top);
}

int main()
{
    stack *stk_handle = NULL;
    char string1[] = "close";
    char string2[] = "the";
    char string3[] = "door";
    char string4[6], string5[6],string6[6];

    stk_handle = create_stack(6, 5);
    push(stk_handle, &(string1));
    push(stk_handle, &(string2));
    push(stk_handle, &(string3));
    pop(stk_handle, string4);
    pop(stk_handle, string5);
    pop(stk_handle, string6);
    return 1;
}

当我编译时,我得到以下编译警告。

$ gcc stack_lib.c
stack_lib.c: In function âpushâ:
stack_lib.c:39: warning: dereferencing âvoid *â pointer
stack_lib.c: In function âpopâ:
stack_lib.c:45: warning: dereferencing âvoid *â pointer

当我运行程序时,我得到以下输出:

Pushed element close to stack. Top is 0
Pushed element the to stack. Top is 1
Pushed element door to stack. Top is 2
Popped element door from stack. Top is 1
Popped element tdoor from stack. Top is 0
Popped element ctdoortdoor from stack. Top is -1

请告诉我哪里出错了。

【问题讨论】:

    标签: c pointers stack void


    【解决方案1】:

    stk_handle-&gt;array[...]void pointer 取消引用。由于 array 成员是 void 指针,因此您不能直接取消引用它(使用取消引用运算符 * 或像您一样使用数组语法)而不强制转换为具体类型。

    请记住,对于数组索引,编译器使用索引乘以基类型来获得正确条目的偏移量。当您有void* 时,基本类型是什么? void 本身不是有效的基类型,那么编译器应该将索引与什么相乘?它根本行不通。

    我的建议是使用int8_t 指针,然后将top 与元素大小相乘:

    typedef struct _stk_
    {
        int top;
        int elemsize;
        int numElem;
        int8_t *array;
    }stack;
    
    ...
    
    memcpy(stk_handle->array + (++stk_handle->top * stk_handle->elmsize), ...);
    

    【讨论】:

    • 太棒了!我多么愚蠢,没有注意到我必须乘以 top * elemsize 来索引数组。谢谢 !以及对 void 指针取消引用的很好解释!非常感谢!
    【解决方案2】:
    1. 那些dereferencing void * pointer 警告可以通过使用适当的指针算法来修复:

      void push (stack *stk_handle, void *element)
      {
              memcpy((char *)stk_handle->array + ++stk_handle->top * stk_handle->elemsize, element, stk_handle->elemsize);
              printf("Pushed element %s to stack. Top is %d\r\n", (char *)element, stk_handle->top);
      }
      
      void pop (stack *stk_handle, void *element)
      {
              memcpy(element, (char *)stk_handle->array + stk_handle->top-- * stk_handle->elemsize, stk_handle->elemsize);
              printf("Popped element %s from stack. Top is %d\r\n", (char *)element, stk_handle->top);
      }
      

      如果您使用gcc,则不需要在stk_handle 之前进行类型转换,请参阅Pointer arithmetic for void pointer in C

    2. push(stk_handle, &amp;(string1));中的&amp;操作是不必要的,你可以写

      push(stk_handle, string1);
      push(stk_handle, string2);
      push(stk_handle, string3);
      

    【讨论】:

    • 谢谢!是注意到 & 不是必需的。
    • @ShankarNarayanan 在 SO,upvote 是说“谢谢”的更恰当的方式。但无论如何,欢迎您。
    • 嗨,leeduhem,对不起。但我没有足够的声誉来投票。因此我无法投票。我是该网站的新用户。
    • @ShankarNarayanan 嘿,别担心。 Upvote 是首选方式,但如果您不能这样做,简单的“谢谢”也可以。
    猜你喜欢
    • 1970-01-01
    • 2012-05-15
    • 2021-04-13
    • 1970-01-01
    • 2015-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-10
    相关资源
    最近更新 更多