I am trying to fill a stack (reserved by malloc) with the value 0xAA or 0b10101010. I think I manage to fill the stack, but printing it, I get different outputs (e83e83e83... or 41f41f41f... for example) depending on my stacksize.
Does anyone have an idea how to solve the problem?
int main(void) {
int status;
int stacksize = 1000;
void* stack=malloc(stacksize);
void* stackTop = stack + stacksize;
for(int i =0; i<stacksize;i++){
stackTop = "10101010";
stackTop --;
}
stackTop =stack + stacksize;
for(int i =0; i<stacksize;i++){
printf("%x", stacksize);
}
return 0;
}
It's somewhat hard to understand from your code and comments, what you're actually trying to do. But if I were to extrapolate on it, you're trying to create a "stack", with an element size of a byte. Here's a quick-and-dirty implementation of such a stack, with bounds checking:
#include <stdio.h>
#include <string.h>
#define STACK_SIZE 1000
struct stack {
int top;
unsigned char elts[STACK_SIZE];
};
static void stack_push(struct stack *s, unsigned char elt) {
if (s->top < STACK_SIZE-1) {
s->elts[s->top++] = elt;
} else {
// No space left in the stack.
}
}
static void stack_pop(struct stack *s) {
if (s->top) {
s->top--;
} else {
// Stack is empty
}
}
static void stack_fill(struct stack *s, unsigned char v) {
memset(s->elts, v, STACK_SIZE);
s->top = STACK_SIZE-1;
}
int main(void) {
// Example driver
struct stack s;
stack_fill(&s, 0xAA);
for (int i = 0; i < STACK_SIZE; i++) {
printf("%d: %02x\n", s.elts[s.top]);
stack_pop(&s);
}
return 0;
}
As an improvement, you could consider e.g. having stack_pop return the popped element, or return some kind of an error if the stack is empty. Or a peek function which returns the top, or an error similar to the one earlier described. However, I omitted them for brevity.
EDIT: To initialize the stack, the only thing required is to set the top member to 0. Initialization function (if needed) is thus trivial to write.
You are filling the stack with strings of chars and reading pointers to them.
The answer given by Paul Hankin in the comment states one of the correct solutions that is using
memset(stack, 0xAA, stacksize);
to fill your stack
thus producing the following code
int main()
{
int status;
int stacksize = 1000;
void* stack = malloc(stacksize);
void* stackTop = stack + stacksize;
memset(stack, 0xAA, stacksize);
for(int i =0; i < stacksize;i++){
printf("%x\n", ((unsigned char*)stack)[i]);
}
return 0;
}
Related
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;
}
I'm trying to create a stack in C using structures but the push() function I wrote is acting strangely. I'm sure it is something obvious that I'm missing but I just couldn't figure out what.
#include <stdio.h>
#define STACK_SIZE 50
typedef struct stack
{
int top;
int items[STACK_SIZE];
}
STACK;
void push(STACK* st, int newitem)
{
st->top++;
st->items[st->top] = newitem;
printf("%d", st->items[st->top]);
}
int main()
{
int n = 1;
STACK* st;
printf("test 1\n");
st->top = -1;
push(st, n);
printf("test 2\n");
return 0;
}
DevCpp only compiles but doesn't execute the code. OnlineGDB runs it but only prints the first test.
This is because your variable STACK* st; was never initialized properly.
Some Important Points:
Don't assign -1 to the length (top), 0 would be better
STACK* st; should be just STACK st;
Your function void push(STACK* st, int newitem) should be declared with static linkage.
Write st->top++
Pass st variable by address to the push() function
Instead of using bare return 0;, use return EXIT_SUCCESS;, which is defined in the header file stdlib.h.
As your total STACK_SIZE is only 50 so, int will be sufficient. But as your STACK_SIZE grows use size_t for your length(top).
use int main(void) { }, instead of int main() { }
NOTE: If STACK_SIZE and top becomes equal means your array is filled completely then further addition of data will lead to Undefined Behavior.
Final Code
#include <stdio.h>
#include <stdlib.h>
#define STACK_SIZE 50
typedef struct stack
{
int top;
int items[STACK_SIZE];
}
STACK;
static void push(STACK* st, int newitem)
{
if(st->top == STACK_SIZE)
{
fprintf(stderr, "stack size reached maximum length\n");
exit(EXIT_FAILURE);
}
st->items[st->top++] = newitem;
printf("%d\n", st->items[st->top - 1]); // we added +1 to `top` in the above line
}
int main(void)
{
int n = 1;
STACK st;
printf("test 1\n");
st.top = 0;
push(&st, n); //pass by address
return EXIT_SUCCESS;
}
I am currently writing my own virtual machine. I have to implement the stack. For whatever reason whenever I call sienna_stack_push(processor->stack, 0); it gives me a segfault.
here is the implementation of the stack
#include <stdlib.h>
#include <stdio.h>
#include "stack.h"
// Helper functions
int is_empty(sienna_stack_t* stack){
return stack->top == -1;
}
int is_full(sienna_stack_t* stack){
return stack->top == stack->max_size;
}
void sienna_stack_init(sienna_stack_t* stack, int capacity){
stack = (sienna_stack_t*)malloc(sizeof(sienna_stack_t));
stack->max_size = capacity;
stack->top = -1;
stack->items = (int*)calloc(capacity, sizeof(int));
}
void sienna_stack_push(sienna_stack_t* stack, int value){
if(is_full(stack)){
printf("FATAL: Stack overflow!\n");
exit(-1);
}
stack->items[++stack->top] = value;
}
int sienna_stack_pop(sienna_stack_t* stack){
if(is_empty(stack)){
printf("FATAL: Stack underflow!\n");
exit(-1);
}
return stack->items[stack->top--];
}
int sienna_stack_peek(sienna_stack_t* stack){
return stack->items[stack->top];
}
here is the stack struct definition
typedef struct {
int max_size;
int top;
int* items;
} sienna_stack_t;
here is me using it
#include <stdio.h>
#include "stack.h"
int main() {
sienna_stack_t stack;
sienna_stack_init(&stack, 0xFFFF);
sienna_stack_push(&stack, 0);
}
and the error is saying it is happening when calling sienna_stack_push();
I guess, you want to reserve sizeof(int) * capacity bytes of memory, but in reality you reserve nothing, because the first parameter of calloc() is 0. Thus, you want to access non-reserved memory, that leads to a crash.
EDIT
Your initialisation is wrong. stack is a static variable. When you call init, you pass the address of this variable. Now you assign an new (anonymous) variable that get lost. You could change stack into a pointer variable:
void sienna_stack_init(sienna_stack_t** stack, int capacity){
*stack = (sienna_stack_t*)malloc(sizeof(sienna_stack_t));
(*stack)->max_size = capacity;
(*stack)->top = -1;
(*stack)->items = (int*)calloc(capacity, sizeof(int));
}
// ...
int main(int argc, char *argv[]){
sienna_stack_t *stack;
sienna_stack_init(&stack, 0xFFF);
sienna_stack_push(stack, 0);
}
For example, if I defined a Stack ADT in C, normally my type definition -using an array based implementation- is like this:
typedef char StackEntry;
typedef struct stack {
int top;
StackEntry entry[MAXSTACK];
} Stack;
How can I make my Stack such that I can have one Stack for characters and another Stack -in the same program- that handles integers for example ?
You could use a stack-structure that is initialized with the size of the elements and that reserves a memory block in terms of bytes to store the elements:
typedef struct stack {
int top;
size_t size;
size_t maxElems;
char content[];
} Stack;
Stack *createStack(size_t size, size_t maxElems) {
Stack *result = malloc(sizeof(Stack)+size*maxElems);
result->top=0;
result->size=size;
result->maxElems=maxElems;
return result;
}
int push(Stack *stack, void *elem) {
if (stack->top == stack->maxElems)
return -1;
memcpy(stack->content + stack->top * stack->size, elem, stack->size);
stack->top++;
return stack->top;
}
int pop(Stack *stack, void *elem) {
if (stack->top == 0)
return -1;
stack->top--;
memcpy(elem, stack->content + stack->top * stack->size, stack->size);
return stack->top;
}
int main() {
Stack *charStack = createStack(sizeof(char), 10);
for (int i=0; i<10; i++) {
char c = 'A'+i;
push(charStack, &c);
}
char c;
while (pop(charStack, &c) >= 0) {
printf("%c\n", c);
}
free(charStack);
Stack *intStack = createStack(sizeof(int), 10);
for (int i=0; i<10; i++) {
push(intStack, &i);
}
int i;
while (pop(intStack, &i) >= 0) {
printf("%d\n", i);
}
free(intStack);
}
Use macros, e.g.
#define STACK_TYPE(type) struct { int top; type entry[MAXSTACK]; }
You may well end up using macros for the stack operations such as push/pop too:
#define STACK_PUSH(stack, value) \
do { if ( (top) < MAXSTACK ) (stack).entry[(stack).top++] = (value); } while (0)
In most cases you wouldn't need to pass the stack type as a macro parameter, since the same syntax works for all stacks.
Sample usage:
STACK_TYPE(int) mystack = { 0 };
STACK_PUSH(mystack, 5);
Obviously there are a lot of different ways you could do the details.
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.