Skip to content

Instantly share code, notes, and snippets.

@savaged
Last active June 14, 2023 10:26
Show Gist options
  • Save savaged/f9313d23c97b383480988d73506bd761 to your computer and use it in GitHub Desktop.
Save savaged/f9313d23c97b383480988d73506bd761 to your computer and use it in GitHub Desktop.
Fun with function pointers in C
// Program.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int (*op_on_triple_ptr)(int, int, int);
typedef int (*op_on_pair_ptr)(int, int);
typedef int (*op_on_single_ptr)(int);
void cout_for_op(char* op_name, int op_result);
void cout_feedback_usage();
int zero_on_triple(int a, int b, int c);
int mult_on_triple(int a, int b, int c);
int sum(int a, int b, int c);
int mean(int a, int b, int c);
int zero_on_pair(int a, int b);
int mult_on_pair(int a, int b);
int add(int a, int b);
int sub(int a, int b);
int zero_on_single(int a);
int inv(int a);
int incr(int a);
int decr(int a);
int do_op_on_triple(op_on_triple_ptr op, int x, int y, int z);
int do_op_on_pair(op_on_pair_ptr op, int x, int y);
int do_op_on_single(op_on_single_ptr op, int i);
op_on_triple_ptr get_op_on_triple_ptr(char* op_name);
op_on_pair_ptr get_op_on_pair_ptr(char* op_name);
op_on_single_ptr get_op_on_single_ptr(char* op_name);
// Program.c
#include "Program.h"
int main(int argc, char **argv)
{
switch (argc)
{
case 5:
cout_for_op(argv[4], do_op_on_triple(get_op_on_triple_ptr(argv[4]), atoi(argv[1]), atoi(argv[2]), atoi(argv[3])));
break;
case 4:
cout_for_op(argv[3], do_op_on_pair(get_op_on_pair_ptr(argv[3]), atoi(argv[1]), atoi(argv[2])));
break;
case 3:
cout_for_op(argv[2], do_op_on_single(get_op_on_single_ptr(argv[2]), atoi(argv[1])));
break;
default:
cout_feedback_usage();
return 1;
}
return 0;
}
void cout_for_op(char* op_name, int op_result) { printf("%s: %i%c", op_name, op_result, '\n'); }
void cout_feedback_usage()
{
printf("Arguments: operand [operand] [operand] operation\n");
printf(" where an operand is an integer and the operation is a short name for a math operation\n");
printf(" like 'mult' (for multiply), sum, mean (average), add, sub (subtract), inv (invert),\n");
printf(" incr (increment) and decr (decrement).\n");
printf(" At least one operand and operation are required and two optional further operands.\n");
printf(" E.g. 8 incr or 8 9 mult or 8 9 7 sum\n");
}
int zero_on_triple(int a, int b, int c) { return 0; }
int mult_on_triple(int a, int b, int c) { return a * b * c; }
int sum(int a, int b, int c) { return a + b + c; }
int mean(int a, int b, int c) { return sum(a, b, c) / 3; }
int zero_on_pair(int a, int b) { return 0; }
int mult_on_pair(int a, int b) { return a * b; }
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }
int zero_on_single(int a) { return 0; }
int inv(int a) { return a * -1; }
int incr(int a) { return ++a; }
int decr(int a) { return --a; }
int do_op_on_triple(op_on_triple_ptr op, int x, int y, int z) { return op(x, y, z); }
int do_op_on_pair(op_on_pair_ptr op, int x, int y) { return op(x, y); }
int do_op_on_single(op_on_single_ptr op, int z) { return op(z); }
op_on_triple_ptr get_op_on_triple_ptr(char* op_name)
{
if (strcmp(op_name, "mult") == 0)
return mult_on_triple;
if (strcmp(op_name, "sum") == 0)
return sum;
if (strcmp(op_name, "mean") == 0)
return mean;
return zero_on_triple;
}
op_on_pair_ptr get_op_on_pair_ptr(char* op_name)
{
if (strcmp(op_name, "mult") == 0)
return mult_on_pair;
if (strcmp(op_name, "add") == 0)
return add;
if (strcmp(op_name, "sub") == 0)
return sub;
return zero_on_pair;
}
op_on_single_ptr get_op_on_single_ptr(char* op_name)
{
if (strcmp(op_name, "inv") == 0)
return inv;
if (strcmp(op_name, "incr") == 0)
return incr;
if (strcmp(op_name, "decr") == 0)
return decr;
return zero_on_single;
}
@savaged
Copy link
Author

savaged commented Jun 12, 2023

Makefile

EXE = funcptr
CFLAGS = -Wall
LDFLAGS =
LIBS =
LD = $(CC)
OBJECTS = *.o

default: all

all: $(EXE)

clean:
	-rm -f $(EXE) # Remove the executable file
	-rm -f $(OBJECTS) # Remove the object files

$(EXE): $(OBJECTS)
	$(CC) $(CFLAGS) $^ -o $(EXE)

$(OBJECTS): Program.c Program.h
	$(LD) $(LDFLAGS) -c $<

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment