2014-04-28 46 views
0

我的大学教授告诉我们,一般堆栈看起来是这样的(我基本上从课程支持文件复制粘贴此):是C中的通用堆栈数据结构链接列表实现吗?

typedef struct 
{ size_t maxe, dime; 
    char *b, *sv, *vf; 
} TStiva, *ASt; 

#define DIME(a) (((ASt)(a))->dime) 
#define BS(a) (((ASt)(a))->b) 
#define SV(a) (((ASt)(a))->sv) 
#define VF(a) (((ASt)(a))->vf) 
#define DIMDIF(s,d) (DIME(s) != DIME(d)) 
#define VIDA(a) (VF(a) == BS(a)) 
#define PLINA(a) (VF(a) == SV(a)) 

// Function Declarations 
void* InitS(size_t d,...); 
int Push(void* a, void* ae); 
int Pop (void* a, void* ae); 
int Top (void* a, void* ae); 

void *InitS(size_t d,...) 
{ ASt a = (ASt)malloc(sizeof (TStiva)); 
    va_list ap; 
    if (!a) return NULL; 
    va_start(ap,d); 
    a->maxe = va_arg(ap,size_t); 
    va_end(ap); 
    a->dime = d; 
    a->b = (char*)calloc(a->maxe, d);   
    if (!a->b) { free(a); return NULL; }  
    a->vf = a->b; 
    a->sv = a->b + d * a->maxe; 
    return (void *)a; 
} 

int Push(void *a, void *ae) 
{ if(PLINA(a)) return 0; 
    memcpy (VF(a), ae, DIME(a)); 
    VF(a) += DIME(a);   
    return 1; 
} 

int Pop(void *a, void *ae)  
{ if(VIDA(a)) return 0; 
    VF(a) -= DIME(a);   
    memcpy (ae, VF(a), DIME(a)); 
    return 1; 
} 

int Top(void *a, void *ae) 
{ if(VIDA(a)) return 0; 
    memcpy (ae, VF(a)-DIME(a), DIME(a)); 
    return 1; 
} 

不管怎么说,这要成为一个通用的堆栈实现与矢量,从中我不明白为什么Top,PushPop函数需要将堆栈数据结构称为void *

通过泛型,它不是想表示数据结构想要容纳的值是通用的?这意味着如果您将泛型数据结构称为typedef而不是void *,这并不意味着它不是通用的。

我在问这个,因为我即将创建一个使用链接列表实现的通用堆栈,我有点困惑。

这是我的通用链表数据结构:

typedef struct Element { 
    struct Element *next; 
    void *value; 
} TElement, *TList, **AList; 

而对于堆栈:

typedef struct Stack { 
    size_t size; 
    TList top; 
} TStack, *AStack; 

/* Function Definitions */ 
TStack InitStack(size_t); 
void DeleteStack(AStack); 
int Push(TStack, void*); 
int Pop(TStack, void*); 
int Top(TStack, void*); 

做任何事情似乎不是通用在我的执行?

+0

您将要'Pop'和'Top'采取'void **',因此您可以为调用者提供指向数据的指针。由于您不知道数据有多大,因此您不能对提供的指针执行“memcpy”操作。 –

+1

必须抵制...抱怨...关于宏观滥用。嗯 – this

+1

我完全让你在那里。我有同样的感觉。我复制粘贴从课程支持。 –

回答

1

通用意味着它可以保存任何数据类型(char*,int*等)或包含任何数据类型。空指针void *C让你投项目本身并获得这些项目了(需要重新扮演他们的检索。

因此,它允许程序,不懂你在你的自定义有数据类型数据结构

参考结构本身(只要你没有指定在所述结构中保存的数据),不会破坏泛型,因此,只要在函数中使用TStack在该栈内操作的数据是一般的(id estvoid *)。

0

void*用于通用目的。把它想象成一个指向内存的指针,当然内存可以容纳任何东西。通过void*你的意思是你不知道你指的是什么,但是你知道你指向某个东西。

+0

是的,我知道。但是为什么我需要将我的栈作为'void *'来引用呢?只有当我不知道我想要保存在我的栈中的数据是什么类型的时候,因此我将这些数据称为void。 –

+0

如果不是'void *',那么是什么?哦,但是等等,你的函数(pop等)实际上会处理你在栈中存储的数据。 – gsamaras

+0

将栈本身称为'TStack',它存储通用的'void *'值。 –

0

是的一个void*可以正确实现一个通用堆栈,但是这会产生一个问题,即您不知道要存储在堆栈中的数据的类型。 void*的概念是它指向一些有效的内存块,但是对内存的类型完全没有线索。因此,使用这个通用堆栈的代码必须明确地进行类型转换。 void*仅用于存储数据,不允许使用它们进行操作。

+0

你有这个问题都是错误的。 –