My problem is I need to pass value from argument (instType, typ1, *op1...) to the structure type tInst.
I'm sure it's a trivial problem but I've spent about 3 hours of my time working on it.
GCC returns segmentation fault 11.
my .h file
typedef enum tInstCode {
I_ADD=0, // (dest, addr, addr) +
I_SUB, // (dest, addr, addr) -
I_MUL, // (dest, addr, addr) *
I_DIV, // (dest, addr, addr) /
} tInstCode;
typedef enum TypeI{
INT=0,
DOUBLE,
STRING
} TypeI;
typedef struct iOperand
{
TypeI type;
void *content;
} iOperand;
typedef struct tInst
{
tInstCode instType;
iOperand *op1;
iOperand *op2;
iOperand *res;
} tInst;
typedef struct ListItem
{
tInst Instruction;
struct ListItem *NextItem;
} tListItem;
my main file :
void generateInstruction(tInstCode instType, TypeI typ1, void *op1, TypeI typ2, void *op2, TypeI typ3, iOperand *op3 )
{
tListOfInstr list;
listInit(&list); //list defined in another file
tInst* I;
I->instType = instType;
I->op1->type = typ1;
I->op1->content = op1;
I->op2 -> type = typ2;
I->op2 -> content = op2;
I->res -> type = typ3;
I->res -> content = op3;
listInsertLast(&list, *I);
}
int main(int argc, char** argv)
{
int a;
a=8;
int *b;
b = &a;
int c;
c=1;
int *d;
d = &c;
generateInstruction(0, DOUBLE, *b, INT, *d, INT, NULL);
}
tInst* I;
I->instType = instType;
You're not allocating memory for I.
As it currently is I is just a pointer with a (potentially) random value. Use malloc to get a suitable address with free memory.
This could be done like this:
tInst* I;
I = malloc(sizeof(tInst));
I->op1 = malloc(sizeof(iOperand));
I->op2 = malloc(sizeof(iOperand));
I->res = malloc(sizeof(iOperand));
Though keep in mind that malloc can fail, so you want to check the return value for NULL.
Related
I'm trying to make a small library for particle management that allows to "expand" struct with user's data (texture, animation frames, etc). The library would know only the size of the expanded struct.
How do I iterate through the array of unknown struct types but known size of a struct?
typedef struct{
int type;
}Base;
typedef struct{
Base base;
int value;
}inherited;
int main(){
size_t size = sizeof(inherited);
int count = 10;
void *b = malloc(size * count);
for (int i = 0; i < count; i++){
// iterate based on known size & send to callback
callback( &( (size)b )[i] );
}
free(b);
return 0;
}
I assume the code that does the malloc and calls callback doesn't know anything about the type of the object, only its size.
#include <stdlib.h>
void *alloc_and_init(size_t nmemb, size_t size, void (*callback)(void *))
{
void *b = calloc(nmemb, size);
if (b)
{
char *p = b;
for (size_t i = 0; i < nmemb; i++)
{
callback(p);
p += size;
}
}
return b;
}
typedef struct{
int type;
}Base;
typedef struct{
Base base;
int value;
}inherited;
void init_inherited(void *p)
{
inherited *obj = p;
/* do initialization of obj->* here */
}
int main(void)
{
int objcount = 10;
inherited *objarr;
objarr = alloc_and_init(objcount, sizeof(*objarr),
init_inherited);
/* ... */
free(objarr);
}
for( inherited *p = b, *e = p + count; p < e; p++ ){
callback(p);
}
char *b = malloc(size * count);
for (int i = 0; i < count; i++){
// iterate based on known size & send to callback
callback( b + i * size );
}
Polymorphism in C is always rather clunky. Basically you have to construct a "vtable" manually. The naive, simplified version below lets each object have its own function pointer. You'll end up with something rather contrived like this:
#include <stdio.h>
#include <stdlib.h>
typedef struct base_t base_t;
typedef void callback_t (const base_t* arg);
struct base_t
{
int type;
callback_t* callback;
};
typedef struct
{
base_t base;
int value;
} inherited_t;
void callback_base (const base_t* arg)
{
puts(__func__);
}
void callback_inherited (const base_t* arg)
{
const inherited_t* iarg = (const inherited_t*)arg;
printf("%s value: %d\n", __func__, iarg->value);
}
int main (void)
{
// allocate memory
base_t* array [3] =
{
[0] = malloc(sizeof(inherited_t)),
[1] = malloc(sizeof(base_t)),
[2] = malloc(sizeof(inherited_t)),
};
// initialize objects
*(inherited_t*)array[0] = (inherited_t){ .base.callback=callback_inherited, .value = 123 };
*(array[1]) = (base_t){ .callback=callback_base };
*(inherited_t*)array[2] = (inherited_t){ .base.callback=callback_inherited, .value = 456 };
for (int i = 0; i < 3; i++)
{
array[i]->callback(array[i]); // now we get polymorphism here
}
}
A more professional version involves writing a translation unit (.h + .c) per "class" and then combine allocation with initialization in the "constructor". It would be implemented with opaque type, see How to do private encapsulation in C? Inside the constructor, set the vtable corresponding to the type of object allocated.
I'd also boldly claim that any OO solution using void* arguments has some design flaw. The interface should be using the base class pointer. Void pointers are dangerous.
How to handle assignment of the functions to one function pointer, each with different number of parameters ? The problem is that parameters differ in number and type. If possible give an example.
Function pointers can be cast in the same way as the other pointers. You will have a generic function pointer (similar to void * for storage types), and use it to hold/pass the address of the function. Before calling the function, you will need to cast it to the correct type.
Here is a working example:
#include <stdio.h>
typedef void (*generic_t)(void);
typedef int (*type2_t)(int);
typedef int (*type3_t)(int, char *s);
void test1(void) {
printf("Test 1\n");
}
int test2(int i) {
printf("Test 2 %i\n",i);
return i;
}
int test3(int i, char *s) {
printf("Test 3 %i, %s\n", i, s);
return i++;
}
int main(void) {
generic_t f1, f2, f3;
f1 = &test1;
f2 = (generic_t)&test2;
f3 = (generic_t)&test3;
f1();
int i = ((type2_t)f2)(10);
i = ((type3_t)f3)(20,"This is test");
}
In addition, you will need to implement a mechanism to recognize what is the type of function that the pointer is pointing to. One approach is to use a struct that holds the pointer and the enum of the type.
Another possibility is to create a union of different function pointer types:
union funptr {
void (*v)();
void (*vi)(int);
void (*vs)(char *);
int (*i)();
int (*ii)(int);
int (*iii)(int, int);
int (*is)(char *);
};
You can use void pointers to pass reference to the in and out parameters. Multiple parameters and return values you can wrap in the structs. The return value may return status.
Sometimes it used in low-level device drivers.
typedef int func(void *, void *);
func *fptr;
struct s1
{
int i;
char *s;
};
int test1(void *in, void *out)
{
printf("Test 1\n");
return 0;
}
int test2(void *in, void *out)
{
int *i = in;
printf("Test 2 %i\n", *i);
return *i;
}
int test3(void *in, void *out)
{
struct s1 *s = in;
printf("Test 3 %i, %s\n", s -> i, s -> s);
return ++s -> i;
}
int main(void)
{
fptr = test1;
fptr(NULL, NULL);
fptr = test2;
fptr((int[]){10}, NULL);
fptr = test3;
printf("Returned value: %d\n", fptr(&(struct s1){20,"This is test"}, NULL));
}
You have to declare a new function pointer type for every different signature that you need to handle.
Is it possible to have a function in C return a 'dynamic' return type
example
printResult (NumOrChar());
void* NumOrChar(void) {
// return int or char
}
void printResult (void* input) {
if (isdigit(input)) {
printf("It's a number");
}
else {
printf("It's not a number");
}
Functions can certainly return void *. But that is a specific pointer type with properties that make it suitable for conveying pointers to objects of any type. It is not a general-purpose wildcard type. Moreover, it does not carry any kind of information about the actual type, if any, of the object to which it points, so there is no way to determine that type dynamically. A C++ programmer might describe this situation as C not providing any RTTI.
Instead, you can return a type that can convey objects of a variety of types, known in advance, with a mechanism to discriminate among those. For example,
union num_or_string {
struct { _Bool is_num; };
struct { _Bool _x1; int num; };
struct { _Bool _x2; char *string; };
};
union num_or_string NumOrChar(void) {
// return a union num_or_string containing an int or a char *
}
void printResult (union num_or_string) {
if (num_or_string.is_num) {
printf("It's a number: %d\n", num_or_string.num);
} else {
printf("It's a string: %s\n", num_or_string.string);
}
}
You can use _Generic in some circumstances
int func_int(int *p)
{
printf("%s\n", __FUNCTION__);
return 5; /* does not make too much sense */
}
float func_float(float *p)
{
printf("%s\n", __FUNCTION__);
return 5.0f; /* does not make too much sense */
}
double func_double(double *p)
{
printf("%s\n", __FUNCTION__);
return 5.0; /* does not make too much sense */
}
#define func(p) _Generic((p), \
int *: func_int, \
float *: func_float, \
double *: func_double)(p) \
Instead of having a block of ifs, one can use a structure of function pointers as a virtual table, including to_string. The following dynamically creates the Type, which can be Num or Letter.
#include <stddef.h> /* offsetof */
#include <stdio.h> /* [|s|sn]printf, fgets, stdin */
#include <stdlib.h> /* malloc, free, strtol */
#include <ctype.h> /* isdigit */
#include <errno.h>
#include <assert.h>
struct Type;
typedef void (*TypeToString)(const struct Type *const, char (*const)[32]);
typedef void (*TypeAction)(struct Type *const);
struct Type {
const struct TypeVt *vt;
};
/* Num extends Type. */
struct Num {
struct Type base;
int value;
};
static struct Num *num_upcast(struct Type *const type) {
return (struct Num *)(void *)((char *)type - offsetof(struct Num, base));
}
static const struct Num *const_num_upcast(const struct Type *const type) {
return (const struct Num *)(const void *)((const char *)type
- offsetof(struct Num, base));
}
static void num_to_string(const struct Type *const type, char (*const a)[32]) {
const struct Num *const num = const_num_upcast(type);
snprintf(*a, sizeof *a, "%d", num->value); /* C99. */
}
static void num_delete(struct Type *const type) {
struct Num *const num = num_upcast(type);
free(num);
}
/* Letter extends Type. */
struct Letter {
struct Type base;
char letter;
};
static struct Letter *letter_upcast(struct Type *const type) {
return (struct Letter *)(void *)((char *)type
- offsetof(struct Letter, base));
}
static const struct Letter *const_letter_upcast(const struct Type *const type) {
return (const struct Letter *)(const void *)((const char *)type
- offsetof(struct Letter, base));
}
static void letter_to_string(const struct Type *const t, char (*const a)[32]) {
const struct Letter *const letter = const_letter_upcast(t);
sprintf(*a, "%c", letter->letter);
}
static void letter_delete(struct Type *const type) {
struct Letter *const letter = letter_upcast(type);
free(letter);
}
static const struct TypeVt {
const char *name;
const TypeToString to_string;
const TypeAction delete;
} num_vt = { "num", &num_to_string, &num_delete },
letter_vt = { "char", &letter_to_string, &letter_delete };
static void type_to_string(const struct Type *const t, char (*const a)[32]) {
assert(t);
t->vt->to_string(t, a);
}
static void type_delete(struct Type *const t) {
assert(t);
t->vt->delete(t);
}
static struct Type *num(const int value) {
struct Num *num = malloc(sizeof *num);
if(!num) return 0;
num->base.vt = &num_vt;
num->value = value;
return &num->base;
}
static struct Type *letter(const char letter) {
struct Letter *l = malloc(sizeof *l);
if(!l) return 0;
l->base.vt = &letter_vt;
l->letter = letter;
return &l->base;
}
static struct Type *read_type(void) {
struct Type *type;
char buffer[64];
if(!fgets(buffer, sizeof buffer, stdin)) return 0;
if(isdigit(buffer[0])) {
long n;
errno = 0;
n = strtol(buffer, 0, 0);
if(errno) return 0;
type = num(n);
} else {
type = letter(buffer[0]);
}
return type;
}
int main(void) {
char a[32];
struct Type *type = 0;
int is_success = 0;
do {
if(!(type = read_type())) break;
type_to_string(type, &a);
printf("\"%s\" is of type %s.\n", a, type->vt->name);
is_success = 1;
} while(0); {
if(type) type_delete(type);
}
if(!is_success) return perror("Failure"), EXIT_FAILURE;
return EXIT_SUCCESS;
}
Probably overkill for your function, but as one has more types, this becomes increasingly attractive. One can consider a union of similar spaced types so that it could be allocated entirely on the stack.
$ bin/numorchar
524645 3456542563456
"524645" is of type num.
$ bin/numorchar
6245635724564357652654245634576
Failure: Result too large
$ bin/numorchar
ata gfddsgsdg
"a" is of type char.
$ bin/numorchar
"
" is of type char.
I guess you are speaking about the C# feature (according to my Google search).
In C, it's not possible unless doing it yourself (other answers show examples). It can be easy or hard depending of your needs. You should think about switching to another language if you really want this (they are sometimes called variants in them).
I want to pass multiple arguments to a function using a void pointer.
void* function(void *params)
{
//casting pointers
//doing something
}
int main()
{
int a = 0
int b = 10;
char x = 'S';
void function(???);
return 0;
}
I know that I have to cast them to a certain variable in my function but I do not know how I can pass my 3 arguments as one void pointer to my function.
I have searched for this problem know quite some time but I could not find anything that would help me.
You could do it like this:
struct my_struct
{
int a;
int b;
char x;
}
void * function(void * pv)
{
struct my_strcut * ps = pv; /* Implicitly converting the void-pointer
/* passed in to a pointer to a struct. */
/* Use ps->a, ps->b and ps->x here. */
return ...; /* NULL or any pointer value valid outside this function */
}
Use it like this
int main(void)
{
struct my_struct s = {42, -1, 'A'};
void * pv = function(&s);
}
Following up on the OP's update:
struct my_struct_foo
{
void * pv1;
void * pv2;
}
struct my_struct_bar
{
int a;
int b;
}
void * function(void * pv)
{
struct my_strcut_foo * ps_foo = pv;
struct my_struct_bar * ps_bar = ps_foo->pv1;
/* Use ps_foo->..., ps_bar->... here. */
return ...; /* NULL or any pointer value valid outside this function */
}
Use it like this
int main(void)
{
struct my_struct_bar s_bar = {42, -1};
struct my_struct_foo s_foo = {&s_bar, NULL};
void * pv = function(&s_foo);
}
The void* is used as a pointer to a "generic" type. Hence, you need to create a wrapping type, cast convert to void* to invoke the function, and cast convert back to your type in the function's body.
#include <stdio.h>
struct args { int a, b; char X; };
void function(void *params)
{
struct args *arg = params;
printf("%d\n", arg->b);
}
int main()
{
struct args prm;
prm.a = 0;
prm.b = 10;
prm.X = 'S';
function(&prm);
return 0;
}
I am just working on a liberty functions in which we define our own datatypes for student and book I have to write a code which finds student by id and book by id these are the two functions. In this functions the pointers which I pass are different but the logic is the same so I got a though that why can't we write one function and pass which thing we want. I mean when we pass the student list it will return the index of student when we pass the book list it will return the book index of the book. Can we use void pointers for that??? Thank you everyone!!!
int findBookId(Book* booklist,int* bcount,unsigned int* tbid)
{
int i;
for (i=0; i<*bcount; i++)
{
if (booklist[i].id==*tbid)
{
return i;
}
}
return NOT_FOUND;
}
int findStuId(Student* stulist,int* scount,unsigned int* tsid)
{
int i;
for (i=0; i<*scount; i++)
{
if (stulist[i].id==*tsid)
{
return i;
}
}
return NOT_FOUND;
}
Assuming you have a student structure:
struct student {
int id;
char name[20];
};
You can imitate qsort() function, to design a parameter to receive a callback function and to receive the size and size of each element if you'd like use void *.
int find_ele(void *base, size_t num, size_t width,
int (*equal)(const void *, const void *),
void *param)
{
int i;
for (i = 0; i < num; ++i) {
if (equal((char *) base + i * width, param)) {
return i;
}
}
return -1;
}
Then, define a "tester":
int student_tester(const void *p1, const void *p2)
{
struct student *sp = (struct student *) p1;
int id = *(int *) p2;
return sp->id == id;
}
In main() function:
int main(void)
{
struct student student_list[] = {
0, "A",
1, "B",
2, "C"
};
int id = 2;
int index = find_ele(student_list, sizeof student_list,
sizeof(struct student), student_tester, &id);
if (index != -1) {
printf("find_ele(id=2) = student_list[%d]; name = %s. \n",
index, student_list[index].name);
} else {
printf("Not found. \n");
}
return 0;
}
This is a bit complicated. You can create macros to simplify it if you don't care.
Rename find_ele to _find_ele, and create a macro:
#define find_ele(base, num, compare, param) _find_ele(base, \
num / sizeof base[0], \
sizeof base[0], \
compare, param)
And create another macro to define a "tester":
#define define_tester(name, type, type_to_find, code) \
int name(const void *_p, const void *param) { \
type *p = (type *) _p; \
type_to_find value = *(type_to_find *) param; \
return (code); \
}
Now you can define a "tester" like this:
define_tester(student_tester, struct student, int,
p->id == value);
Complete code:
#include <stdio.h>
int _find_ele(void *base, size_t num, size_t width,
int (*equal)(const void *, const void *),
void *param)
{
int i;
for (i = 0; i < num; ++i) {
if (equal((char *) base + i * width, param)) {
return i;
}
}
return -1;
}
#define find_ele(base, num, compare, param) _find_ele(base, \
num / sizeof base[0], \
sizeof base[0], \
compare, param)
#define define_tester(name, type, type_to_find, code) \
int name(const void *_p, const void *param) { \
type *p = (type *) _p; \
type_to_find value = *(type_to_find *) param; \
return (code); \
}
struct student {
int id;
char name[20];
};
define_tester(student_tester, struct student, int,
p->id == value);
int main(void)
{
struct student student_list[] = {
0, "A",
1, "B",
2, "C"
};
int id = 2;
int index = find_ele(student_list, sizeof student_list, student_tester, &id);
if (index != -1) {
printf("find_ele(id=2) = student_list[%d]; name = %s. \n",
index, student_list[index].name);
} else {
printf("Not found. \n");
}
return 0;
}
Yes you can use void*, but while dereferencing you should know the exact type of the pointer.
So, when you can your function, add another parameter:
type = 0 for Books
= 1 for students
And then your function becomes:
int findId(void* list,int* count,unsigned int* tbid, int type)
{
Book* booklist=NULL;
Student* stulist=NULL;
int i;
if(type===0)
booklist = (Book*) list;
else if(type==1)
stulist = (Student*) list;
else
// Handle this undefined case
// And now use the same type variable to decide which pointer to use to match the values
. . . .
}
Yes you can use void pointer, if you are trying to store address of your array..Your array may contain integer types or some other datatypes stored, it doesn't matter, but right typecasting while de-referencing the void pointer is important.
I don't think you can use void* in these functions.
If you changed your functions to one and created something like:
int findObjId(void* objlist,int* count, unsigned int* objid)
{
int i;
for (i=0; i<*scount; i++)
{
if (objlist[i].id==*objid)
{
return i;
}
}
return NOT_FOUND;
}
you won't be able to extract the data from objlist. Neither *objlist, nor objlist[i] can be dereferenced to evaluate to an object. The compiler will definitely stop you from using any such statement.
If you have the option, switch to C++. Using templates, you can accomplish your goal without breaking a sweat.