11
Using a union
- #include <stdio.h>
- #include <stdlib.h>
- #include <assert.h>
- typedef enum { INTEGER, STRING, REAL, POINTER } type;
- typedef struct {
- type type;
- union {
- int integer;
- char *string;
- float real;
- void *pointer;
- } x;
- } value;
- typedef struct _stack {
- int top;
- int size;
- value *data;
- } *stack;
- stack stack_create(unsigned siz) {
- stack sk = (stack)malloc(sizeof (struct _stack));
- if (!sk)
- return 0;
- sk->data = (value *)malloc(sizeof (value) * siz);
- if (!sk->data)
- return 0;
- sk->size = siz;
- sk->top = 0;
- return sk;
- }
- void stack_delete(stack sk) {
- free(sk->data);
- free(sk);
- }
- void stack_push(stack sk, value v) {
- assert(sk->top < sk->size);
- sk->data[sk->top++] = v;
- }
- value stack_pop(stack sk) {
- assert(sk->top > 0);
- return sk->data[--sk->top];
- }
- void stack_add(stack sk) {
- value v1 = stack_pop(sk), v2 = stack_pop(sk);
- assert((v1.type == INTEGER || v1.type == REAL) && v1.type == v2.type);
- if (v1.type == INTEGER)
- v1.x.integer += v2.x.integer;
- else
- v1.x.real += v2.x.real;
- stack_push(sk, v1);
- }
- void stack_exec(stack sk) {
- value v = stack_pop(sk);
- assert(v.type == POINTER);
- ((void (*)(stack))(v.x.pointer))(sk);
- }
- void stack_dot(stack sk) {
- value v = stack_pop(sk);
- switch (v.type) {
- case INTEGER:
- fprintf(stdout, "%d", v.x.integer);
- break;
- case REAL:
- fprintf(stdout, "%f", v.x.real);
- break;
- case STRING:
- fputs(v.x.string, stdout);
- break;
- case POINTER:
- fprintf(stdout, "0x%x", (unsigned)v.x.pointer);
- break;
- default:
- break;
- }
- }
- #define STACKSIZE 100
- main() {
- stack sk;
- value op1, op2, s, nl, pf;
- sk = stack_create(STACKSIZE);
- nl.type = STRING;
- nl.x.string = "\n";
- s.type = STRING;
- s.x.string = " = ";
- op1.type = INTEGER;
- op1.x.integer = 1;
- op2.type = INTEGER;
- op2.x.integer = 2;
- stack_push(sk, nl);
- stack_push(sk, op1);
- stack_push(sk, op2);
- stack_add(sk);
- stack_push(sk, s);
- stack_dot(sk);
- stack_dot(sk);
- stack_dot(sk);
- op1.type = REAL;
- op1.x.real = 1.0;
- op2.type = REAL;
- op2.x.real = -1;
- pf.type = POINTER;
- pf.x.pointer = stack_add;
- stack_push(sk, nl);
- stack_push(sk, op1);
- stack_push(sk, op2);
- stack_push(sk, pf);
- stack_exec(sk);
- stack_push(sk, s);
- stack_dot(sk);
- stack_dot(sk);
- stack_dot(sk);
- stack_delete(sk);
- }
$ gcc -o stack stack.c
$ ./stack
= 3
= 0.000000
Comments