// This stack is implemented by void pointer, so it is GENERIC. // // How the void pointer allows assignments of different data types: // first, a normal pointer is binded to a data type, so it knows the // number of bytes of the data it points to. second, it has an address, // which is the start-address of the data. so they can tell the compiler // where to start and where to stop accessing the data. // // but void pointer is binded to no data type,it only knows the starting-address. // so it can be forcely assigned to any pointers, thus allowing assignments of // all data types. so what we do is: when we create the stack, we MALLOC a block // of free space, and we take an integer of 'size_t', the typesize, which // specifies the length of the data. We use the function MEMCPY, which directly // access the addresses,to push the data in the stack and pop data out. // // The difference from the definiton: // the stack pointer here is different from the definition. // when the stack is empty, top == base. // when an element is pushed in, top points to the address after the last byte // of the element. so the top always points to the next available space.
// This stack is implemented by void pointer, so it is GENERIC. // // How the void pointer allows assignments of different data types: // first, a normal pointer is binded to a data type, so it knows the // number of bytes of the data it points to. second, it has an address, // which is the start-address of the data. so they can tell the compiler // where to start and where to stop accessing the data. // // but void pointer is binded to no data type,it only knows the starting-address. // so it can be forcely assigned to any pointers, thus allowing assignments of // all data types. so what we do is: when we create the stack, we MALLOC a block // of free space, and we take an integer of 'size_t', the typesize, which // specifies the length of the data. We use the function MEMCPY, which directly // access the addresses,to push the data in the stack and pop data out. // // The difference from the definiton: // the stack pointer here is different from the definition. // when the stack is empty, top == base. // when an element is pushed in, top points to the address after the last byte // of the element. so the top always points to the next available space.
#include<stdio.h> #include<stdlib.h>
structRecord { void *top; void *base; int stacksize; int typesize; };
// GNU defines the arithmetic of void* equals to char(which is defined as byte). // ANSI says we cannot do arithmetic on void* because we don't know the type. // so when we update the top pointer, first regard it as an int, and convert it // back when we are finished.