C : How do you simulate an 'instance'? - c

Let's say that I have the following code in C that represents a stack :
#define MAX 1000
int arr[MAX];
static int counter = 0;
isstackempty()
{
return counter <= 0;
}
void push(int n)
{
if (counter >= MAX) {
printf("Stack is full. Couldn't push %d", n);
return;
}
arr[counter++] = n;
}
int pop(int* n)
{
if(isstackempty() || n == 0) {
printf("Stack is empty\n");
return 0;
}
*n = arr[--counter];
return 1;
}
The above code is in a stack.c file and the function prototypes are in a header.
Now, coming from a C# and OO background, if I would want to separate stacks to use in my application, in an OO language I would create two instances. But in C, how do you handle such a scenario?
Say I want to use two separate stacks in my C code...with the above code, how would I go about it?

Put the array arr inside a struct.
struct stack {
int arr[MAX];
...
}
This struct becomes your instance. You can then declare it on the stack:
struct stack mystack;
or on the heap using malloc:
struct stack *mystack = malloc(sizeof(struct stack));
You also need to pass a pointer to the instance as the first parameter to any function manipulating the instance.

The C way to do this is to wrap up all the state for your 'object' into a struct, and then explicitly pass it into all the functions that operate on stacks, so it should be:
typedef struct _stack {
int arr[MAX];
int counter;
} stack;
int isstackempty(stack *s)
{
return s->counter <= 0;
}
int push(stack *s, int n)
{
if (s->counter >= MAX) {
printf("Stack is full. Couldn't push %d", n);
return -1;
}
arr[s->counter++] = n;
return 0
}
int pop(stack *s, int *n)
{
if(isstackempty(s) || n == 0) {
printf("Stack is empty\n");
return -1;
}
*n = arr[--s->counter];
return 0;
}
The issue with your example is you're writing the function definitions like we have a class-based object structure, which C doesn't have. The easiest way to think about how it's done in C is that you're writing methods that require you to explicitly pass in the 'this' parameter.
Also you can have the equivalent of constructors and destructors, which can further abstract your 'object'.
stack* newStack() {
stack* s = malloc(sizeof(stack));
s->counter = 0;
return s;
}
void freeStack(stack* s) {
free(s);
}

One (extremely simplistic) way of going about it is to define a struct that represents a stack:
typedef struct {
int arr[MAX];
int counter = 0;
} myStack;
and then rewrite push() and pop() to operate on an instance of myStack:
int push(myStack *s, int n)
{
if (s->counter >= MAX) {
printf("Stack is full. Couldn't push %d", n);
return -1;
}
s->arr[(s->counter)++] = n;
return s->counter;
}
int pop(myStack *s, int* n)
{
if(0 == s->counter || 0 == n) {
printf("Stack is empty\n");
return -1;
}
*n = s->arr[--(s->counter)];
return 1;
}
(Also added a meaningful return value and error value to push(). YMMV.)

I hope you find this paper useful. It gives more than one answer to your question :)
Sixteen Ways to Stack a Cat

Simply make your 'this' pointer explicit:
struct stack* create_stack();
void push(struct stack* mystack, int n);
void pop(struct stack* mystack, int* n);

My answer to this other question has a complete working example of an OO data buffer structure in C.

A dynamically allocated structre-per-instance is the right way to go. A point of detail - if you are writing a more generally used API it is probably a good idea to engage in data hiding for better abstraction.
The simplest way of doing this is keep the definition of the internal structure in the C file (or a private header file), and typedef a void pointer to (e.g.) 'stack_handle_t'. It is this type that is returned from your 'constructor' and is passed back in to each other function.
The implementation is aware that the value of the handle is in fact a pointer to a structure and at the beginning of each function simply does:
int pop(stack_handle_t handle, int* n)
{
stack *p_stack = (stack *)handle;
...
Even better than that is to use an internally allocated identifier instead, whether this is an index into an array of these structs or simply an identifier which can be matched against one of a (linked?) list of structs.
Obviously all this is irrelevant if its only for use internal to your project, in those circumstances it is just making unnecessary work and over-complication.

Related

How to reduce amount of memory taken by function pointers in structs? [duplicate]

I'm trying to do a "class model" in C in which I define a struct that represents the class and inside it I define function pointers to represent methods, like this:
//ClassName.h
typedef struct struct_ClassName ClassName;
struct ClassName
{
char a;
char b;
char c;
void (*method1)(ClassName*, char);
void (*method2)(ClassName*, char);
...
void (*methodN)(ClassName*, char);
};
void initClassName(ClassName*);
//ClassName.c
#include "ClassName.h"
static void method1(ClassName *this_c, char c);
static void method2(ClassName *this_c, char c);
...
static void methodN(ClassName *this_c, char c);
void initClassName(ClassName *this_c)
{
this_c->method1 = &method1;
this_c->method2 = &method2;
...
this_c->methodN = &methodN;
}
void method1(ClassName *this_c, char c)
{
//do something
}
void method2(ClassName *this_c, char c)
{
//do something
}
...
void methodN(ClassName *this_c, char c)
{
//do something
}
Everything works fine but, somewhere in the code, I define an array:
...
ClassName objects[200];
for(i = 0; i < 200; i++)
{
initClassName(&objects[i]);
}
...
Because of the function pointers, the memory usage associated to this array is quite high (I have several "methods" in this "class").
Considering that this is a code that will run in an embedded system, is there a better way to do it?
Defining functions outside the structure could be a possibility but in my opinion it does not respect what I'm trying to emulate.
I have to use only C, not C++.
What you have created is a very dynamic system where each object instance can have its own set of method implementations. That's why it uses so much memory.
Another approach is an implementation closer to early C++ (before multiple inheritance) where all instance of the same class share the same vtable. The vtable contains the function pointers.
typedef struct struct_ClassName ClassName;
typedef struct struct_ClassName_vtable ClassName_vtable;
struct ClassName_vtable
{
void (*method1)(ClassName*, char);
void (*method2)(ClassName*, char);
...
void (*methodN)(ClassName*, char);
}
struct ClassName
{
ClassName_vtable* _vtable;
char a;
char b;
char c;
};
void initClassName(ClassName*);
static void method1(ClassName *this_c, char c);
static void method2(ClassName *this_c, char c);
...
static void methodN(ClassName *this_c, char c);
ClassName_vtable _ClassName_vtable = {
method1,
method2,
...,
methodN
};
void initClassName(ClassName *this_c)
{
this_c->_vtable = _ClassName_vtable;
}
That way, the OO overhead per instance is only the size of a pointer. It's also easier to create subclasses.
A method call looks like this:
ClassName* obj = ...;
obj->vtable->method2(obj, 'a');
ClassName objects[200];
for(i = 0; i < 200; i++)
initClassName(&objects[i]);
I will show you a stripped-off version of something I use here
for similar effect. It is hard to say when a certain size is huge in terms of pointers or whatever. Each environment has their truth and this can be useless or useful...
Anyway, the ideia is encapsulation. And in C we have no this pointer. C is not C++ or java or javascript. Each class instance must have a table of function pointers for the methods. We need to build these tables. This is how virtual classes are implemented in others languages anyway. And if each class element can allocate memory code is needed to allocate and free memory.
TL;DR
Below is a C example of a program that builds and uses an array of classes. In this case an array of stacks. It shows a mechanism of building stacks of mixed things. Each array item has all that is needed to manage his own stack instance, be it of a trivial type or a complex structure. It can be easily changed to implement other tyoes of classes in C.
Please do not bother warning me that I cast the return of malloc(). I , as many others, do not like implicit things. And I know that C-FAQ is a never-updated thing from the end of the '90s so no need to reference this either.
An example: a static STACK container
typedef struct
{
int data[SIZE];
int limit; // capacity
int size; // actual
} Stack;
This is it: a simple stack of int values. Let us say we want to declare a vector of stacks of different things, but in C. And use methods on them. If we use trivial types --- in C++ we say the struct is trivialy constructible --- things can get easier, but if we are about to use structs we need to know about how to manipulate stack elements, since they can allocate memory.
We are writing a container so the methods of the class must work for any underlying data. And we have no iterators like C++ STL. Here we are implementing the POP TOP and PUSH methods for stacks, and a toString() method like in java to print values on the screen.
For each possible content in the container we need to have a constructor, a
destructor, a copy constructor and a display method. In this example we have just 2 types of stacks: a stack of int and a stack of struct Sample:
typedef struct
{
size_t _id;
char name[30];
char phone[20];
} Sample;
We can add others just by writing the required 4 functions.
main.c example
int main(void)
{
srand(220804); // for the factory functions
Stack* class_array[2] = {
create(4, create_i, copy_i, destroy_i, show_i),
create(3, create_st, copy_st, destroy_st, show_st)};
printf("\n\n=====> Testing with STACK of int\n\n");
class_test(class_array[0], factory_i);
printf(
"\n\n=====> Testing with STACK of struct "
"Sample\n\n");
class_test(class_array[1], factory_st);
class_array[0]->destroy(class_array[0]);
class_array[1]->destroy(class_array[1]);
return 0;
}
Each instance of Stack has pointers to the stack methods and to the functions that manipulate the stack data, so we can have a single class_test() function that does the following:
builds a stack of the required size, 4 or 3 in the example
fills the stack with data generated by factory functions (in production the logic builds the data)
shows the stack contents
removes all stack elements, one by one
At the end the destructor is called for eack stack.
The class.h file
typedef void* (PVFV)(void*);
typedef int (PIFV)(void*);
typedef struct
{
size_t size_;
size_t lim_;
void** data_;
PVFV* copy;
PVFV* destroy;
int (*show)(void*,const char*); // for testing
// constructor and destructor for container elements
PVFV* create_1;
PVFV* copy_1;
PVFV* destroy_1;
PIFV* show_1;
// member functions
PIFV* POP;
int (*PUSH)(void*,void*);
PVFV* TOP;
PIFV* empty;
size_t (*size)(void*);
} Stack;
Stack* create(
size_t,
void* (*)(void*),
void* (*)(void*),
void* (*)(void*),
int (*)(void*));
int class_test(Stack*, void* (*)());
the example output
=====> Testing with STACK of int
Stack is empty
POP() on empty stack returned -2
TOP() on empty stack returned NULL
Calls PUSH until error
Value inserted: 42
Value inserted: 41
Value inserted: 40
Value inserted: 39
Stack now has 4 elements
Stack has 4 of 4 elements:
42
41
40
39
Calls POP() until error
Stack size: 3
Stack size: 2
Stack size: 1
Stack size: 0
=====> Testing with STACK of struct Sample
Stack is empty
POP() on empty stack returned -2
TOP() on empty stack returned NULL
Calls PUSH until error
Value inserted: 0195 Sample id#0195 +76(203)6840-195
Value inserted: 0943 Sample id#0943 +35(686)9368-943
Value inserted: 0152 Sample id#0152 +16(051)8816-152
Stack now has 3 elements
Stack has 3 of 3 elements:
0096 Sample id#0096 +24(477)0418-096
0037 Sample id#0037 +27(214)3509-037
0836 Sample id#0836 +68(857)4634-836
Calls POP() until error
Stack size: 2
Stack size: 1
Stack size: 0
the logic
For each tye of element we need to write the 4 functions: they can alocate memory and be very complex or they can be trivial, but the class methods need to handle any case.
code for struct Sample in stack_struct.h###
#pragma once
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
void* copy_st(void*);
void* create_st(void*);
void* destroy_st(void*);
void* factory_st();
typedef struct
{
size_t _id;
char name[30];
char phone[20];
} Sample;
void* create_st(void* el)
{
return factory_st();
}
void* copy_st(void* el)
{
if (el == NULL) return NULL;
Sample* e = (Sample*)malloc(sizeof(Sample));
*e = *((Sample*)el);
return e;
}
void* destroy_st(void* el)
{
if (el == NULL) return NULL;
free(el);
return NULL;
}
int show_st(void* el)
{
if (el == NULL) return 0;
Sample* e = (Sample*)el;
printf(
" %04d %15s %20s\n",
(int) e->_id, e->name, e->phone);
return 0;
}
void* factory_st()
{
Sample* e = (Sample*)malloc(sizeof(Sample));
e->_id = rand() % 1000;
sprintf(e->name, "Sample id#%04d", (int)e->_id);
memset(e->phone, 0, sizeof(e->phone));
e->phone[0] = '+';
for (int i = 1; i <= 17; i += 1)
e->phone[i] = '0' + rand() % 10;
e->phone[3] = '(';
e->phone[7] = ')';
e->phone[12] = '-';
e->phone[13] = e->name[11];
e->phone[14] = e->name[12];
e->phone[15] = e->name[13];
e->phone[16] = e->name[14];
e->phone[17] = 0;
return (void*)e;
}
code for int elements stack_int.h_###
#pragma once
#include <stdio.h>
#include <stdlib.h>
void* create_i(void* el)
{
int* e = (int*)malloc(sizeof(int));
*e = *((int*)el);
return (void*)e;
}
void* copy_i(void* el)
{
if (el == NULL) return NULL;
int* e = (int*)malloc(sizeof(int));
*e = *( (int*)el );
return e;
}
void* destroy_i(void* el)
{
if (el == NULL) return NULL;
free(el);
return NULL;
}
int show_i(void* el)
{
if (el == NULL) return 0;
int v = *((int*)el);
printf(" %d\n", v);
return 0;
}
void* factory_i()
{
static int i = 42;
int* new_int = (int*)malloc(sizeof(int));
*new_int = i;
i -= 1;
return (void*)new_int;
}
The class implementation class.c
#include "class.h"
#include <stdio.h>
#include <stdlib.h>
void* Copy__(void*);
void* Destroy__(void*);
int POP__(void*);
int PUSH__(void*, void*);
int Show__(void*, const char*);
void* TOP__(void*);
int empty__(void*);
size_t size__(void*);
Stack* create(
size_t sz, void* (*create)(void*), void* (*copy)(void*),
void* (*destroy)(void*), int (*show)(void*))
{
Stack* stack = (Stack*)malloc(sizeof(Stack));
if (stack == NULL) return NULL;
stack->size_ = 0;
stack->lim_ = sz;
stack->data_ = (void*)malloc(sz * sizeof(void*));
stack->copy = Copy__;
stack->destroy = Destroy__;
stack->show = Show__;
stack->create_1 = create;
stack->copy_1 = copy;
stack->destroy_1 = destroy;
stack->show_1 = show;
stack->POP = POP__;
stack->PUSH = PUSH__;
stack->TOP = TOP__;
stack->empty = empty__;
stack->size = size__;
return stack;
}
void* Copy__(void* one) { return NULL; };
void* Destroy__(void* stack)
{ // before destructing a stack we need to
// destroy all elements
if (stack == NULL) return NULL;
Stack* st = (Stack*)stack;
for (size_t ix = 0; ix < st->size_; ix += 1)
(st->destroy_1)(st->data_[ix]);
free(st->data_);
free(st);
return NULL;
};
int POP__(void* stack)
{
if (stack == NULL) return -1; // no stack
Stack* st = stack;
if (st->size_ == 0) return -2; // empty
st->size_ -= 1; // one less
return 0; // ok
}
int PUSH__(void* el, void* stack)
{
if (el == NULL) return -1; // no element
if (stack == NULL) return -2; // no stack
Stack* st = (Stack*)stack;
if (st->size_ == st->lim_) return -3; // full
void* new_el = st->create_1(el); // copy construct
st->data_[st->size_] = new_el;
st->size_ += 1; // one up
return 0; // ok
}
int Show__(void* stack, const char* title)
{
if (stack == NULL) return -1;
Stack* st = stack;
if (title != NULL) printf("%s\n", title);
if (st->size_ == 0)
{
printf("Stack is empty\n");
return 0;
}
for (size_t ix = 0; ix < st->size_; ix += 1)
st->show_1(st->data_[ix]);
printf("\n");
return 0;
}
void* TOP__(void* stack)
{
if (stack == NULL) return NULL; // no stack
Stack* st = stack;
if (st->size_ == 0) return NULL; // empty
return st->data_[st->size_ - 1]; // ok
}
int empty__(void* stack)
{
if (stack == NULL) return 1; // empty??
return ((Stack*)stack)->size_ == 0;
}
size_t size__(void* stack)
{
if (stack == NULL) return 1; // empty??
return ((Stack*)stack)->size_;
}
///////////// TEST FUNCTION ///////////////
int class_test(Stack* tst, void* (*factory)())
{
if (tst == NULL) return -1;
// is stack empty?
if (tst->empty(tst))
printf("Stack is empty\n");
else
printf("Stack: %zd elements\n", tst->size(tst));
int res = tst->POP(tst);
printf("POP() on empty stack returned %d\n", res);
void* top = tst->TOP(tst);
if (top == NULL)
printf("TOP() on empty stack returned NULL\n");
else
{
printf(
"\nTOP() on empty stack returned NOT NULL!\n");
return -2;
}
printf("Calls PUSH until error\n\n");
void* one = factory();
int value = *(int*)one;
while (tst->PUSH(one, tst) == 0)
{
printf("Value inserted:");
tst->show_1(one);
free(one);
one = factory();
}
free(one); // last one, not inserted
printf("Stack now has %zd elements\n", tst->size(tst));
char title[80] = {" "};
sprintf(
title, "\nStack has %zd of %zd elements:\n",
tst->size_, tst->lim_);
tst->show(tst, title);
// agora esvazia a pilha ate dar erro
printf("\nCalls POP() until error\n");
while (tst->POP(tst) == 0)
printf("Stack size: %I32d\n", (int)tst->size(tst));
return 0;
};
The complete main.c program
#include <stdio.h>
#include "class.h"
#include "stack_int.h"
#include "stack_struct.h"
int main(void)
{
srand(220804);
Stack* class_array[2] = {
create(4, create_i, copy_i, destroy_i, show_i),
create(3, create_st, copy_st, destroy_st, show_st)};
printf("\n\n=====> Testing with STACK of int\n\n");
class_test(class_array[0], factory_i);
printf(
"\n\n=====> Testing with STACK of struct "
"Sample\n\n");
class_test(class_array[1], factory_st);
class_array[0]->destroy(class_array[0]);
class_array[1]->destroy(class_array[1]);
return 0;
}

Class model in C

I'm trying to do a "class model" in C in which I define a struct that represents the class and inside it I define function pointers to represent methods, like this:
//ClassName.h
typedef struct struct_ClassName ClassName;
struct ClassName
{
char a;
char b;
char c;
void (*method1)(ClassName*, char);
void (*method2)(ClassName*, char);
...
void (*methodN)(ClassName*, char);
};
void initClassName(ClassName*);
//ClassName.c
#include "ClassName.h"
static void method1(ClassName *this_c, char c);
static void method2(ClassName *this_c, char c);
...
static void methodN(ClassName *this_c, char c);
void initClassName(ClassName *this_c)
{
this_c->method1 = &method1;
this_c->method2 = &method2;
...
this_c->methodN = &methodN;
}
void method1(ClassName *this_c, char c)
{
//do something
}
void method2(ClassName *this_c, char c)
{
//do something
}
...
void methodN(ClassName *this_c, char c)
{
//do something
}
Everything works fine but, somewhere in the code, I define an array:
...
ClassName objects[200];
for(i = 0; i < 200; i++)
{
initClassName(&objects[i]);
}
...
Because of the function pointers, the memory usage associated to this array is quite high (I have several "methods" in this "class").
Considering that this is a code that will run in an embedded system, is there a better way to do it?
Defining functions outside the structure could be a possibility but in my opinion it does not respect what I'm trying to emulate.
I have to use only C, not C++.
What you have created is a very dynamic system where each object instance can have its own set of method implementations. That's why it uses so much memory.
Another approach is an implementation closer to early C++ (before multiple inheritance) where all instance of the same class share the same vtable. The vtable contains the function pointers.
typedef struct struct_ClassName ClassName;
typedef struct struct_ClassName_vtable ClassName_vtable;
struct ClassName_vtable
{
void (*method1)(ClassName*, char);
void (*method2)(ClassName*, char);
...
void (*methodN)(ClassName*, char);
}
struct ClassName
{
ClassName_vtable* _vtable;
char a;
char b;
char c;
};
void initClassName(ClassName*);
static void method1(ClassName *this_c, char c);
static void method2(ClassName *this_c, char c);
...
static void methodN(ClassName *this_c, char c);
ClassName_vtable _ClassName_vtable = {
method1,
method2,
...,
methodN
};
void initClassName(ClassName *this_c)
{
this_c->_vtable = _ClassName_vtable;
}
That way, the OO overhead per instance is only the size of a pointer. It's also easier to create subclasses.
A method call looks like this:
ClassName* obj = ...;
obj->vtable->method2(obj, 'a');
ClassName objects[200];
for(i = 0; i < 200; i++)
initClassName(&objects[i]);
I will show you a stripped-off version of something I use here
for similar effect. It is hard to say when a certain size is huge in terms of pointers or whatever. Each environment has their truth and this can be useless or useful...
Anyway, the ideia is encapsulation. And in C we have no this pointer. C is not C++ or java or javascript. Each class instance must have a table of function pointers for the methods. We need to build these tables. This is how virtual classes are implemented in others languages anyway. And if each class element can allocate memory code is needed to allocate and free memory.
TL;DR
Below is a C example of a program that builds and uses an array of classes. In this case an array of stacks. It shows a mechanism of building stacks of mixed things. Each array item has all that is needed to manage his own stack instance, be it of a trivial type or a complex structure. It can be easily changed to implement other tyoes of classes in C.
Please do not bother warning me that I cast the return of malloc(). I , as many others, do not like implicit things. And I know that C-FAQ is a never-updated thing from the end of the '90s so no need to reference this either.
An example: a static STACK container
typedef struct
{
int data[SIZE];
int limit; // capacity
int size; // actual
} Stack;
This is it: a simple stack of int values. Let us say we want to declare a vector of stacks of different things, but in C. And use methods on them. If we use trivial types --- in C++ we say the struct is trivialy constructible --- things can get easier, but if we are about to use structs we need to know about how to manipulate stack elements, since they can allocate memory.
We are writing a container so the methods of the class must work for any underlying data. And we have no iterators like C++ STL. Here we are implementing the POP TOP and PUSH methods for stacks, and a toString() method like in java to print values on the screen.
For each possible content in the container we need to have a constructor, a
destructor, a copy constructor and a display method. In this example we have just 2 types of stacks: a stack of int and a stack of struct Sample:
typedef struct
{
size_t _id;
char name[30];
char phone[20];
} Sample;
We can add others just by writing the required 4 functions.
main.c example
int main(void)
{
srand(220804); // for the factory functions
Stack* class_array[2] = {
create(4, create_i, copy_i, destroy_i, show_i),
create(3, create_st, copy_st, destroy_st, show_st)};
printf("\n\n=====> Testing with STACK of int\n\n");
class_test(class_array[0], factory_i);
printf(
"\n\n=====> Testing with STACK of struct "
"Sample\n\n");
class_test(class_array[1], factory_st);
class_array[0]->destroy(class_array[0]);
class_array[1]->destroy(class_array[1]);
return 0;
}
Each instance of Stack has pointers to the stack methods and to the functions that manipulate the stack data, so we can have a single class_test() function that does the following:
builds a stack of the required size, 4 or 3 in the example
fills the stack with data generated by factory functions (in production the logic builds the data)
shows the stack contents
removes all stack elements, one by one
At the end the destructor is called for eack stack.
The class.h file
typedef void* (PVFV)(void*);
typedef int (PIFV)(void*);
typedef struct
{
size_t size_;
size_t lim_;
void** data_;
PVFV* copy;
PVFV* destroy;
int (*show)(void*,const char*); // for testing
// constructor and destructor for container elements
PVFV* create_1;
PVFV* copy_1;
PVFV* destroy_1;
PIFV* show_1;
// member functions
PIFV* POP;
int (*PUSH)(void*,void*);
PVFV* TOP;
PIFV* empty;
size_t (*size)(void*);
} Stack;
Stack* create(
size_t,
void* (*)(void*),
void* (*)(void*),
void* (*)(void*),
int (*)(void*));
int class_test(Stack*, void* (*)());
the example output
=====> Testing with STACK of int
Stack is empty
POP() on empty stack returned -2
TOP() on empty stack returned NULL
Calls PUSH until error
Value inserted: 42
Value inserted: 41
Value inserted: 40
Value inserted: 39
Stack now has 4 elements
Stack has 4 of 4 elements:
42
41
40
39
Calls POP() until error
Stack size: 3
Stack size: 2
Stack size: 1
Stack size: 0
=====> Testing with STACK of struct Sample
Stack is empty
POP() on empty stack returned -2
TOP() on empty stack returned NULL
Calls PUSH until error
Value inserted: 0195 Sample id#0195 +76(203)6840-195
Value inserted: 0943 Sample id#0943 +35(686)9368-943
Value inserted: 0152 Sample id#0152 +16(051)8816-152
Stack now has 3 elements
Stack has 3 of 3 elements:
0096 Sample id#0096 +24(477)0418-096
0037 Sample id#0037 +27(214)3509-037
0836 Sample id#0836 +68(857)4634-836
Calls POP() until error
Stack size: 2
Stack size: 1
Stack size: 0
the logic
For each tye of element we need to write the 4 functions: they can alocate memory and be very complex or they can be trivial, but the class methods need to handle any case.
code for struct Sample in stack_struct.h###
#pragma once
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
void* copy_st(void*);
void* create_st(void*);
void* destroy_st(void*);
void* factory_st();
typedef struct
{
size_t _id;
char name[30];
char phone[20];
} Sample;
void* create_st(void* el)
{
return factory_st();
}
void* copy_st(void* el)
{
if (el == NULL) return NULL;
Sample* e = (Sample*)malloc(sizeof(Sample));
*e = *((Sample*)el);
return e;
}
void* destroy_st(void* el)
{
if (el == NULL) return NULL;
free(el);
return NULL;
}
int show_st(void* el)
{
if (el == NULL) return 0;
Sample* e = (Sample*)el;
printf(
" %04d %15s %20s\n",
(int) e->_id, e->name, e->phone);
return 0;
}
void* factory_st()
{
Sample* e = (Sample*)malloc(sizeof(Sample));
e->_id = rand() % 1000;
sprintf(e->name, "Sample id#%04d", (int)e->_id);
memset(e->phone, 0, sizeof(e->phone));
e->phone[0] = '+';
for (int i = 1; i <= 17; i += 1)
e->phone[i] = '0' + rand() % 10;
e->phone[3] = '(';
e->phone[7] = ')';
e->phone[12] = '-';
e->phone[13] = e->name[11];
e->phone[14] = e->name[12];
e->phone[15] = e->name[13];
e->phone[16] = e->name[14];
e->phone[17] = 0;
return (void*)e;
}
code for int elements stack_int.h_###
#pragma once
#include <stdio.h>
#include <stdlib.h>
void* create_i(void* el)
{
int* e = (int*)malloc(sizeof(int));
*e = *((int*)el);
return (void*)e;
}
void* copy_i(void* el)
{
if (el == NULL) return NULL;
int* e = (int*)malloc(sizeof(int));
*e = *( (int*)el );
return e;
}
void* destroy_i(void* el)
{
if (el == NULL) return NULL;
free(el);
return NULL;
}
int show_i(void* el)
{
if (el == NULL) return 0;
int v = *((int*)el);
printf(" %d\n", v);
return 0;
}
void* factory_i()
{
static int i = 42;
int* new_int = (int*)malloc(sizeof(int));
*new_int = i;
i -= 1;
return (void*)new_int;
}
The class implementation class.c
#include "class.h"
#include <stdio.h>
#include <stdlib.h>
void* Copy__(void*);
void* Destroy__(void*);
int POP__(void*);
int PUSH__(void*, void*);
int Show__(void*, const char*);
void* TOP__(void*);
int empty__(void*);
size_t size__(void*);
Stack* create(
size_t sz, void* (*create)(void*), void* (*copy)(void*),
void* (*destroy)(void*), int (*show)(void*))
{
Stack* stack = (Stack*)malloc(sizeof(Stack));
if (stack == NULL) return NULL;
stack->size_ = 0;
stack->lim_ = sz;
stack->data_ = (void*)malloc(sz * sizeof(void*));
stack->copy = Copy__;
stack->destroy = Destroy__;
stack->show = Show__;
stack->create_1 = create;
stack->copy_1 = copy;
stack->destroy_1 = destroy;
stack->show_1 = show;
stack->POP = POP__;
stack->PUSH = PUSH__;
stack->TOP = TOP__;
stack->empty = empty__;
stack->size = size__;
return stack;
}
void* Copy__(void* one) { return NULL; };
void* Destroy__(void* stack)
{ // before destructing a stack we need to
// destroy all elements
if (stack == NULL) return NULL;
Stack* st = (Stack*)stack;
for (size_t ix = 0; ix < st->size_; ix += 1)
(st->destroy_1)(st->data_[ix]);
free(st->data_);
free(st);
return NULL;
};
int POP__(void* stack)
{
if (stack == NULL) return -1; // no stack
Stack* st = stack;
if (st->size_ == 0) return -2; // empty
st->size_ -= 1; // one less
return 0; // ok
}
int PUSH__(void* el, void* stack)
{
if (el == NULL) return -1; // no element
if (stack == NULL) return -2; // no stack
Stack* st = (Stack*)stack;
if (st->size_ == st->lim_) return -3; // full
void* new_el = st->create_1(el); // copy construct
st->data_[st->size_] = new_el;
st->size_ += 1; // one up
return 0; // ok
}
int Show__(void* stack, const char* title)
{
if (stack == NULL) return -1;
Stack* st = stack;
if (title != NULL) printf("%s\n", title);
if (st->size_ == 0)
{
printf("Stack is empty\n");
return 0;
}
for (size_t ix = 0; ix < st->size_; ix += 1)
st->show_1(st->data_[ix]);
printf("\n");
return 0;
}
void* TOP__(void* stack)
{
if (stack == NULL) return NULL; // no stack
Stack* st = stack;
if (st->size_ == 0) return NULL; // empty
return st->data_[st->size_ - 1]; // ok
}
int empty__(void* stack)
{
if (stack == NULL) return 1; // empty??
return ((Stack*)stack)->size_ == 0;
}
size_t size__(void* stack)
{
if (stack == NULL) return 1; // empty??
return ((Stack*)stack)->size_;
}
///////////// TEST FUNCTION ///////////////
int class_test(Stack* tst, void* (*factory)())
{
if (tst == NULL) return -1;
// is stack empty?
if (tst->empty(tst))
printf("Stack is empty\n");
else
printf("Stack: %zd elements\n", tst->size(tst));
int res = tst->POP(tst);
printf("POP() on empty stack returned %d\n", res);
void* top = tst->TOP(tst);
if (top == NULL)
printf("TOP() on empty stack returned NULL\n");
else
{
printf(
"\nTOP() on empty stack returned NOT NULL!\n");
return -2;
}
printf("Calls PUSH until error\n\n");
void* one = factory();
int value = *(int*)one;
while (tst->PUSH(one, tst) == 0)
{
printf("Value inserted:");
tst->show_1(one);
free(one);
one = factory();
}
free(one); // last one, not inserted
printf("Stack now has %zd elements\n", tst->size(tst));
char title[80] = {" "};
sprintf(
title, "\nStack has %zd of %zd elements:\n",
tst->size_, tst->lim_);
tst->show(tst, title);
// agora esvazia a pilha ate dar erro
printf("\nCalls POP() until error\n");
while (tst->POP(tst) == 0)
printf("Stack size: %I32d\n", (int)tst->size(tst));
return 0;
};
The complete main.c program
#include <stdio.h>
#include "class.h"
#include "stack_int.h"
#include "stack_struct.h"
int main(void)
{
srand(220804);
Stack* class_array[2] = {
create(4, create_i, copy_i, destroy_i, show_i),
create(3, create_st, copy_st, destroy_st, show_st)};
printf("\n\n=====> Testing with STACK of int\n\n");
class_test(class_array[0], factory_i);
printf(
"\n\n=====> Testing with STACK of struct "
"Sample\n\n");
class_test(class_array[1], factory_st);
class_array[0]->destroy(class_array[0]);
class_array[1]->destroy(class_array[1]);
return 0;
}

transfer of pointer from function to function

I have a problem, because while loading data from the console, a bug is popping up I think it's a tricky thing to pass the indicator through the function, but I don't know how to fix it.
#include<stdio.h>
#include<stdlib.h>
typedef struct rn{
int n; /**numerator**/
unsigned d; /**denomirator**/
} rationalNumber;
typedef struct dot{
rationalNumber x;
rationalNumber y;
} point;
int gcd(int a, int b)
{
if(b!=0)
return gcd(b,a%b);
return a;
}
void input(rationalNumber *a)
{
int nwd;
if (scanf("%d/%u",&(a->n), &(a->d)) == 1) a->d=1;
else
{
nwd = abs(gcd(a->n, a->d));
a->n = a->n/nwd;
a->d = a->d/nwd;
}
}
void load_point(point *a, void(*function)(rationalNumber *))
{
function(&a->x);
function(&a->y);
}
int main(void)
{
rationalNumber *z;
point *a;
load_point(a, input);
return 0;
}
I've got this message : Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)
in this place : if (scanf("%d/%u",&(a->n), &(a->d)) == 1) a->d=1;
You're creating pointers that point to nothing in particular and then pass these on to the function which never initializes them, allocates memory for them, and trusts that they're valid, but they're not.
Remember that point* a is a pointer, not an allocation.
An easy solution is to use local variables instead of pointers:
int main(void)
{
rationalNumber z;
point a;
load_point(&a, input);
return 0;
}

C doesn't put data in arrays or varibles

I'm the beginner in C programming< for now I'm using linux and tried both gcc and clang compilers. However, I'm facing the one problem, sometimes C doesn't put data in the array or variable. For example, there is one of my simple codes, that doesn't work completely:
#include <stdio.h>
#define size 10
struct stack{
int structTop;
int elemNum[size];
};
int create (struct stack s);
int full (struct stack s);
void push (int elem, struct stack s);
void main() {
struct stack s1;
struct stack s2;
struct stack s3;
int a = 545;
create(s1);
push(a, s1);
push(5, s1);
push(a, s1);
push(1, s1);
push(6, s1);
push(4, s1);
push(7, s1);
push(8, s1);
int i = 0;
while (i<4){
printf("%d\n", s1.elemNum[i]);
i++;
}
}
int create (struct stack s){
s.structTop = -1;
return 0;
}
int full(struct stack s){
if(s.structTop == size-1) {
return 1;
}
else {
return 0;
}
}
void push(int elem, struct stack s){
if(full(s)){
printf("Stack is full");
}
else {
s.structTop++;
s.elemNum[s.structTop]=elem;
}
}
As output I'm getting data, wich was inside array from the beginning (zeros or random numbers). Also it was only one of the codes, i have couple of larger ones, that have the same problem. Variables and arrays inside them are working 50/50, sometimes yes, sometimes no, even if declarations and functions are the same. Someone told me, that it could be the matter of compiler, but i tried different ones and also have a friend with the same Kali linux as me facing this problem on a different PC.
You need to pass pointers to the struct, i.e. int create (struct stack *s) instead of int create (struct stack s). The same for push. Otherwise, you pass a copy and in the function, you will alter a copy and not the originally passed object from main.
The thing why it sometimes worked, at least partially, is that when passing objects by value, these values will be put temporarily on a stack; It seems that the same object from main had several time been pushed right on the same position on the stack, such that it seemed as if it was always the same object. But - as you recognised - this really occasional.
The signatures of your methods should look as follows:
int create (struct stack *s);
int full (const struct stack *s);
void push (int elem, struct stack *s);
Note that - since passing now pointers - you have to access the elements of s using -> (and not .), e.g. s->structTop = -1 instead of s.structTop = -1; and that you have to pass the address of a stack (not the stack itself, e.g. push(a, &s1) instead of push(a, s1).
Note further that in int full (const struct stack *s), I declared s as const, as the function does not intend to alter any value of the members of s.
#include <stdio.h>
#define size 10
struct stack{
int structTop;
int elemNum[size];
};
int create (struct stack *s);
int full (const struct stack *s);
void push (int elem, struct stack *s);
int main() {
struct stack s1;
int a = 545;
create(&s1);
push(a, &s1);
push(5, &s1);
push(a, &s1);
push(1, &s1);
push(6, &s1);
push(4, &s1);
push(7, &s1);
push(8, &s1);
int i = 0;
while (i<4){
printf("%d\n", s1.elemNum[i]);
i++;
}
}
int create (struct stack *s){
s->structTop = -1;
return 0;
}
int full(const struct stack *s){
if(s->structTop == size-1) {
return 1;
}
else {
return 0;
}
}
void push(int elem, struct stack *s){
if(full(s)){
printf("Stack is full");
}
else {
s->structTop++;
s->elemNum[s->structTop]=elem;
}
}

C array struct function pointer

How do you create a function pointer with struct table such as
static struct {
int pid;
int queue[MAXPROCS];
} semtab[MAXSEMS];
I think I understand how to make OO equivalent in C using function pointer with this post, but how can I do with when my struct is an array. I'm still a little iffy with the syntax.
Would it be something like
static struct {
int pid;
int queue[MAXPROCS];
void (*fncPtr_enqueue)(int) = enqueue;
// or is it void(*enqueue)(semtable[]*) ?
int (*fcnPtr_dequeue)() = dequeue;
} semtab[MAXSEMS];
void enqueue(int i) { /* code */ }
int dequeue() { /* code */ }
// then to use it, it would be like this?
void foo() {
semtab[5].enqueue(6);
}
Use
static struct {
int pid;
int queue[MAXPROCS];
void (*fncPtr_enqueue)(int); // This defines a member fncPtr_enqueue
int (*fncPtr_dequeue)(); // Note that you had fcnPtr_ in your post.
// I have fncPtr_ here.
} semtab[MAXSEMS];
void enqueue(int i) { /* code */ }
int dequeue() { /* code */ }
Each object in semtab that needs to have valid function pointers needs to be updated.
semtab[0].fncPtr_enqueue = enqueue;
semtab[0].fncPtr_dequeue = dequeue;
You could use:
static struct
{
int pid;
int queue[MAXPROCS];
void (*enqueue)(int);
int (*dequeue)(void);
} semtab[MAXSEMS];
void enqueue(int i) { /* code */ }
int dequeue(void) { /* code */ }
void foo(void)
{
semtab[5].enqueue(6);
}
Changes include:
Systematic names for structure member pointers (instead of mixed fncPtr and fcnPtr prefixes).
No attempt to initialize in the structure definition.
Add void to function prototypes to indicate no arguments. In C (and in contrast to C++), an empty pair of brackets (parentheses) means "a function taking an undefined number of arguments, but not one which has a variable argument list with ... ellipsis".
Because of (1), the original invocation is OK. (With the original code, you'd have needed semtab[5].fncPtr_enqueue(6); — or even (*semtab[5].fncPtr_enqueue)(6);)
You would still have to ensure that the function pointers in the table are all initialized.
With GCC and C99 or C11 compilation, you could initialize the array using:
static struct
{
int pid;
int queue[MAXPROCS];
void (*enqueue)(int);
int (*dequeue)(void);
} semtab[MAXSEMS] =
{
[0 ... MAXSEMS-1] = { .enqueue = enqueue, .dequeue = dequeue }
};
The [0 ... MAXSEMS-1] part is a GCC extension. Observe that a space is required after the 0 to avoid problems with the 'maximal munch' rule.
As JS1 mentioned in the comments, it's actually pretty pointless to do this with the example you have, as you're not achieving anything with the indirection if you're not going to vary the value of those pointers.
That being said, here's an example using a stack (because the logic is easier than a queue, and this is a simple example). Note that you must pass a pointer to the stack to each of your member functions, because while C++ member functions have an implicit this argument, C functions never do. You also need to give your struct a name, otherwise you won't be able to refer to it in the abstract, which you need to do.
This program uses the same struct to implement two variations of a stack, one normal one, and one which unnecessarily shouts at you when you push or pop:
#include <stdio.h>
#include <stdlib.h>
enum {
STACKSIZE = 1024
};
struct stack {
int stack[STACKSIZE];
size_t top;
void (*push)(struct stack *, int);
int (*pop)(struct stack *);
void (*destroy)(struct stack *);
};
void stack_push(struct stack * this, int i)
{
if ( this->top == STACKSIZE ) {
fprintf(stderr, "Queue full!\n");
exit(EXIT_FAILURE);
}
this->stack[this->top++] = i;
}
void stack_push_verbose(struct stack * this, int i)
{
stack_push(this, i);
printf("** PUSHING %d ONTO STACK! **\n", i);
}
int stack_pop(struct stack * this)
{
if ( this->top == 0 ) {
fprintf(stderr, "Stack empty!\n");
exit(EXIT_FAILURE);
}
return this->stack[--this->top];
}
int stack_pop_verbose(struct stack * this)
{
const int n = stack_pop(this);
printf("** POPPING %d FROM STACK! **\n", n);
return n;
}
void stack_destroy(struct stack * this)
{
free(this);
}
struct stack * stack_create(void)
{
struct stack * new_stack = malloc(sizeof * new_stack);
if ( !new_stack ) {
perror("Couldn't allocate memory");
exit(EXIT_FAILURE);
}
new_stack->top = 0;
new_stack->push = stack_push;
new_stack->pop = stack_pop;
new_stack->destroy = stack_destroy;
return new_stack;
}
struct stack * stack_verbose_create(void)
{
struct stack * new_stack = stack_create();
new_stack->push = stack_push_verbose;
new_stack->pop = stack_pop_verbose;
return new_stack;
}
int main(void)
{
struct stack * stack1 = stack_create();
struct stack * stack2 = stack_verbose_create();
stack1->push(stack1, 4);
stack1->push(stack1, 3);
stack1->push(stack1, 2);
printf("Popped from stack1: %d\n", stack1->pop(stack1));
stack2->push(stack2, 5);
stack2->push(stack2, 6);
printf("Popped from stack2: %d\n", stack2->pop(stack2));
printf("Popped from stack1: %d\n", stack1->pop(stack1));
printf("Popped from stack1: %d\n", stack1->pop(stack1));
printf("Popped from stack2: %d\n", stack2->pop(stack2));
stack1->destroy(stack1);
stack2->destroy(stack2);
return 0;
}
with output:
paul#horus:~/src/sandbox$ ./stack
Popped from stack1: 2
** PUSHING 5 ONTO STACK! **
** PUSHING 6 ONTO STACK! **
** POPPING 6 FROM STACK! **
Popped from stack2: 6
Popped from stack1: 3
Popped from stack1: 4
** POPPING 5 FROM STACK! **
Popped from stack2: 5
paul#horus:~/src/sandbox$
Note that we use the exact same struct stack for both types of stack - the differences between them are implemented by having the function pointers point to different functions in each case. The only visible difference to the user is that one is created with stack_create(), and the other is created with stack_create_verbose(). In all other respects, they're used identically, so you can see the polymorphism at work.

Resources