How to pass an array of struct using pointer in c/c++? - c

in C code I'm stuck to pass an array of struct to a function, here's the code that resembles my problem:
typedef struct
{
int x;
int y;
char *str1;
char *str2;
}Struct1;
void processFromStruct1(Struct1 *content[]);
int main()
{
Struct1 mydata[]=
{ {1,1,"black","cat"},
{4,5,"red","bird"},
{6,7,"brown","fox"},
};
processFromStruct1(mydata);//how?!?? can't find correct syntax
return 0;
}
void processFromStruct1(Struct1 *content[])
{
printf("%s", content[1]->str1);// if I want to print 'red', is this right?
...
}
Compile error in msvc is something like this:
error C2664: 'processFromStruct1' : cannot convert parameter 1 from 'Struct1 [3]' to 'Struct1 *[]'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
How to solve this? tnx.

You almost had it, either this
void processFromStruct1(Struct1 *content);
or this
void processFromStruct1(Struct1 content[]);
and, as Alok points out in comments, change this
content[1]->str1
to this
content[1].str1
Your array is an array of structures, not an array of pointers, so once you select a particular structure with [1] there is no need to further dereference it.

Try
processFromStruct1( & mydata[ i ] ); // pass the address of i-th element of mydata array
and the method to
void processFromStruct1(Struct1 *content )
{
printf("%s", content->str1);
...
}
(2nd part already noted by John Knoeller and Alok).

John Knoeller gave the perfect syntax , I am trying to explain some basic things,
I hope that it willsolve your confusions in future.
This is very similar to passing pointer to a function in C.
Of course struct is also a pointer,
so we can pass the value in 2 ways
0. Via pointer
0. Via array ( since we are using array of struct )
so the problem is simple now ,
You have to give the data type of a variable as we do in normal pointers ,
here the data type is user-defined ( that means struct ) Struct1 then variable name,
that variable name can be pointer or array name ( choose a compatible way ).

This works for me. Changed structs to C++ style.
struct Struct1
{
int x;
int y;
char *str1;
char *str2;
};
Struct1 mydata[]=
{ {1,1,"black","cat"},
{4,5,"red","bird"},
{6,7,"brown","fox"},
};
void processFromStruct1(Struct1 content[]);
int main()
{
processFromStruct1(&mydata[1]);
return 0;
}
void processFromStruct1(Struct1 content[])
{
printf("%s",content->str1);
}
output: red

Perhaps a proper re-factoring from the future:
#include <stdio.h>
typedef struct
{
int x;
int y;
char *str1;
char *str2;
} struct_1;
static void proc_the_struct_1_arr (
const int count_ ,
// array arg declared with min number of arguments
// also can not be null
struct_1 content[ static count_ ]
)
{
for (unsigned j = 0; j < count_; ++j)
printf("x:%-4dy:%-4d%-12s%-12s\n", content[j].x,content[j].y,content[j].str1,content[j].str2);
}
int main( void )
{
struct_1 mydata[3]= {
{.str1 = "black", .str2 = "cat" },
{.str1 = "red", .str2 = "bird"},
{.str1 = "brown", .str2 = "fox" },
};
proc_the_struct_1_arr (3,mydata);
return 0;
}
Godbolt
Obviously proc_the_struct_1_arr declaration is interesting. That actually uses Variably Modified Types (VMT). That is a legal syntax only for array arguments.
That is not slower vs the pointer to array solution:
static void proc_the_struct_1_arr_pointer (
const int count_ ,
// array arg not declared with min
// required number of arguments
struct_1 (*arr_ptr)[ /* static no allowed here */ count_ ]
);
I assume the compiler "rewrites" the above to the array pointer, anyway. On the second option arr_ptr can be a null argument.

You can try the prototype as void processFromStruct1(Struct1 content[]); and then the declaration should be like void processFromStruct1(Struct1 content[]).

Related

Can I pass parameters into a function if I only have a pointer to a function in C?

I have a program, what it does isn't too important, I am mostly curious of the following:
If I have a struct that has pointers to a function, can I pass parameters into the function using that pointer? Here is part of my code
edit: I realized I was a little vague:
So is there anyway to use the variable 'x' of type funcs, to pass parameters into the my_closeit and my_openit using the pointer's initialized by x = {&openit, &closeit}; in the main function? By doing x -> or x. ?
Another Edit:
Would it be x.openit(some pointer, some int); ?
#include<stdio.h>
int my_openit(char* name, int prot);
void my_closeit(void);
typedef struct funcs
{
int (*openit)(char *name, int prot);
void (*closeit)(void);
}funcs;
//I know the first 'funcs' is unnecessary
int main()
{
funcs x = {&my_openit, &my_closeit};
return 0;
}
int my_openit(char* name, int prot)
{
return 0;
}
void my_closeit(void)
{
}
can I pass parameters into the function using that pointer?
Yes, obviously, or it wouldn't be of any use. In your case:
int result = x.openit("something", 123);
Yes, just use function call expression through the pointers:
int r = x.openit("myfile",0);
x.closeit();

Incompatible pointer array 2D

Im new with C and i have to do a program for school.
I have 3 classes:
lab11.c(main)
procs.c
procs.h
Im getting this error everytime:
error: conflicting types for 'transposarMatriu'|
\procs.h|171|note: previous declaration of 'transposarMatriu' was here|
My code (main):
char matriu_ori[T_DIM_MAX][T_DIM_MAX];
char matriu_dst[T_DIM_MAX][T_DIM_MAX]
transposarMatriu(matriu_ori, *matriu_dst, mida, mida);
Procs.h
extern void transposarMatriu(char matriu_ori[][T_DIM_MAX], char matriu_dst[][T_DIM_MAX], int nfiles, int ncols);
Procs.c
void transposarMatriu(char matriu_ori[][T_DIM_MAX], char *matriu_dst[][T_DIM_MAX], int nfiles, int ncols) {
int c,d;
for (c = 0; c < nfiles; c++) {
for( d = 0 ; d < ncols ; d++ ) {
*matriu_dst[d][c] = matriu_ori[c][d];
}
}
}
The problem comes from the discrepancy between the function definition in procs.c and its declaration in procs.h.
Procs.h
extern void transposarMatriu(char matriu_ori[][T_DIM_MAX], char matriu_dst[][T_DIM_MAX], int nfiles, int ncols);
The function signature must be identical, in this case is not, as you can see, in procs.c the second argument is of type char*, instead of char as in procs.h.
Procs.c
void transposarMatriu(char matriu_ori[][T_DIM_MAX], char *matriu_dst[][T_DIM_MAX], int nfiles, int ncols) {
...
TL;DR: remove the asterisk in lab11.c and procs.c: transposarMatriu([...] *matriu_dst [...])
The function definition for transposarMatriu in procs.c declares matriu_dst to be of type array of arrays of pointers to char (*matriu_dst[][]) (see C Right-Left Rule if you want to learn to decipher C declarations). Probably not what you intended and it's also a mismatch from the function declaration in procs.h.
I assume you intended matriu_dst to be "modifiable" like in call-by-reference, but there's no need to. Arrays are passed to functions by address, so they're "modifiable" by default.
By the same reasoning, there's no need to dereference matriu_dst in main.c (apply the * operator). In fact, doing so means you're passing the first element of the array to the function (an array of chars).

How to correctly pass a pointer to an array of pointers?

In my code I need to pass a pointer to an array of pointers as a function argument. Code snippets:
struct foo * foos[] = {NULL, NULL, NULL};
some_function(&foos);
and:
static void some_function(struct foo ** foos) {
foos[0] = get_a_foo();
/* some more code here */
}
This works as expected (after some_function() returns, foos[] contains the pointers I set there), but I get a compiler warning for the call to some_function():
note: expected ‘struct foo **’ but argument is of type ‘struct foo * (*)[3]’
What’s the correct way to accomplish what I want (i.e. pass a pointer to the array of pointers to the function, so that the function can change pointers in the array)?
Pass it as some_function(foos)
struct foo ** is a pointer to a (single) pointer to a struct foo, not a pointer to an array of pointers, hence the compiler warning.
An easy way to silence the compiler warning is to call the function as follows:
some_function(&foos[0]);
This will pass a pointer to the first member, i.e. a struct foo **, rather than to the whole array; the address is the same in both cases.
If I understand what you are trying to do (fill your array of pointers with a call to a function), then your understanding of how to accomplish that is a bit unclear. You declare foos, which itself is an array. (an array of what? pointers).
You can treat it just like you would treat an array of char (from the standpoint that you can simply pass the array itself as a parameter to a function and operate on the array within a function) You can do that and have the changes visible in the caller because despite the array address itself being a copy in the function, the values it holds (the individual pointer address) remains the same.
For example:
#include <stdio.h>
char *labels[] = { "my", "dog", "has", "fleas" };
void fillfoos (char **f, int n)
{
int i;
for (i = 0; i < n; i++)
f[i] = labels[i];
}
int main (void) {
char *foos[] = { NULL, NULL, NULL };
int i, n = sizeof foos / sizeof *foos;
fillfoos (foos, n);
for (i = 0; i < n; i++)
printf ("foos[%d] : %s\n", i, foos[i]);
return 0;
}
Above foos is simply treated as an array passed to the function fillfoos which then loops over each pointer within foos filling it with the address to the corresponding string-literal contained in labels. The contents of foos is then available back in main, e.g.
Example Use/Output
$ ./bin/fillptp
foos[0] : my
foos[1] : dog
foos[2] : has
If I misunderstood your question, please let me know and I'm happy to help further.
You need a pointer to an array as clearly mentioned in the warning.
Below is a minimal code sample that explains the same.
#include<stdio.h>
typedef struct foo{
}FOO;
static void some_function(FOO* (*foos)[]) {
// foos above is a pointer to an array of pointers.
// Refer the link to start with a simple example.
// Access it like foos[0][0] which is the same as (*foos)[0]
/* some more code here */
}
int main(int argc, char **argv) {
FOO* foos[]={0,0,0}; // Here you have an array of pointers
some_function(&foos);
}

Function Returning Itself

Is it possible to declare some function type func_t which returns that type, func_t?
In other words, is it possible for a function to return itself?
// func_t is declared as some sort of function pointer
func_t foo(void *arg)
{
return &foo;
}
Or would I have to use void * and typecasting?
No, you cannot declare recursive function types in C. Except inside a structure (or an union), it's not possible to declare a recursive type in C.
Now for the void * solution, void * is only guaranteed to hold pointers to objects and not pointers to functions. Being able to convert function pointers and void * is available only as an extension.
A possible solution with structs:
struct func_wrap
{
struct func_wrap (*func)(void);
};
struct func_wrap func_test(void)
{
struct func_wrap self;
self.func = func_test;
return self;
}
Compiling with gcc -Wall gave no warnings, but I'm not sure if this is 100% portable.
You can't cast function pointers to void* (they can be different sizes), but that's not a problem since we can cast to another function pointer type and cast it back to get the original value.
typedef void (*fun2)();
typedef fun2 (*fun1)();
fun2 rec_fun()
{
puts("Called a function");
return (fun2)rec_fun;
}
// later in code...
fun1 fp = (fun1)((fun1)rec_fun())();
fp();
Output:
Called a function
Called a function
Called a function
In other words, is it possible for a function to return itself?
It depends on what you mean by "itself"; if you mean a pointer to itself then the answer is yes! While it is not possible for a function to return its type a function can return a pointer to itself and this pointer can then be converted to the appropriate type before calling.
The details are explained in the question comp.lang.c faq: Function that can return a pointer to a function of the same type.
Check my answer for details.
Assume the function definition
T f(void)
{
return &f;
}
f() returns a value of type T, but the type of the expression &f is "pointer to function returning T". It doesn't matter what T is, the expression &f will always be of a different, incompatible type T (*)(void). Even if T is a pointer-to-function type such as Q (*)(void), the expression &f will wind up being "pointer-to-function-returning-pointer-to-function", or Q (*(*)(void))(void).
If T is an integral type that's large enough to hold a function pointer value and conversion from T (*)(void) to T and back to T (*)(void) is meaningful on your platform, you might be able to get away with something like
T f(void)
{
return (T) &f;
}
but I can think of at least a couple of situations where that won't work at all. And honestly, its utility would be extremely limited compared to using something like a lookup table.
C just wasn't designed to treat functions like any other data item, and pointers to functions aren't interchangeable with pointers to object types.
what about something like this:
typedef void* (*takesDoubleReturnsVoidPtr)(double);
void* functionB(double d)
{
printf("here is a function %f",d);
return NULL;
}
takesDoubleReturnsVoidPtr functionA()
{
return functionB;
}
int main(int argc, const char * argv[])
{
takesDoubleReturnsVoidPtr func = functionA();
func(56.7);
return 0;
}
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
typedef void *(*fptr)(int *);
void *start (int *);
void *stop (int *);
void *start (int *a) {
printf("%s\n", __func__);
return stop(a);
}
void *stop (int *a) {
printf("%s\n", __func__);
return start(a);
}
int main (void) {
int a = 10;
fptr f = start;
f(&a);
return 0;
}
It is not possible for a function to return itself by value. However it is possible itself to return by a pointer.
C allows to define function types that take undefined number of parameters and those those types are compatible with function types that take defined parameters.
For example:
typedef void fun_t();
void foo(int);
fun_t *fun = foo; // types are fine
Therefore the following function would work.
void fun(void (**ptr)()) {
*ptr = &fun;
}
And below you can find the exemplary usage:
#include <stdio.h>
void fun(void (**ptr)()) {
puts("fun() called");
*ptr = &fun;
}
int main() {
void (*fp)();
fun(&fp); /* call fun directly */
fp(&fp); /* call fun indirectly */
return 0;
}
The code compiles in pedantic mode with no warnings for C89 standard.
It produces the expected output:
fun() called
fun() called
There's a way, you just try this:
typedef void *(*FuncPtr)();
void *f() { return f; }
int main() {
FuncPtr f1 = f();
FuncPtr f2 = f1();
FuncPtr f3 = f2();
return 0;
}
If you were using C++, you could create a State object type (presuming the state machine example usage) wherein you declare an operator() that returns a State object type by reference or pointer. You can then define each state as a derived class of State that returns each appropriate other derived types from its implementation of operator().

Can you printf value from a void * in C

Ok, I'm trying to do this, but it isn't working becuase I'm not dereferencing the pointer... is there a way to do it without making a switch statement for the type?
typedef struct
{
char *ascii_fmtstr;
int len;
int (*deserializer)(void *in, const char *ascii);
int (*serializer)(const void *in, char *ascii);
} FORMAT;
const FORMAT formats[]=
{
{"%d\n", 2/2} //Int
,{"%s\n", STRSIZE/2} //String
,{"%.4f\n", 4/2} //Float
,{"%lld", 4/2} //Long-Long
,{"%s\n", STRSIZE/2} //Time
};
typedef struct {
int fmtindex;
void * vp;
} JUNK;
float f = 5.0f;
int i=1;
char foo[]="bar";
JUNK j[] = {
{2, &f}
,{0, &i}
,{1, foo}};
void dump(void)
{
int i;
for(i=0;i<2;i++)
printf(formats[j[i].fmtindex].ascii_fmtstr, j[i].vp);
}
It seems like you're using void * as a cheap union. That's a pretty bad idea. I think you'll find unions in conjunction with enums and switches make this look so much neater, in C. You'll find the switch amongst the #ifdef SWITCH ... #else, and the switchless version amongst the #else ... #endif.
#include <stdio.h>
struct object {
enum type {
d=0,
s=1,
f=2,
lld=3,
time=4
} type;
union instance {
int d;
char *s;
float f;
long long lld;
char *time;
} instance;
};
#ifdef SWITCH
void print_object(struct object *o) {
switch (o->type) {
case d: printf("%d", o->instance.d); break;
case s: printf("%s", o->instance.s); break;
case f: printf("%f", o->instance.f); break;
case lld: printf("%lld", o->instance.lld); break;
case time: printf("%s", o->instance.time); break;
};
}
#else
void print_d(struct object *o);
void print_s(struct object *o);
void print_f(struct object *o);
void print_lld(struct object *o);
void print_time(struct object *o);
void print_object(struct object *o) {
void (*print_functions[])(struct object *) = {
[d] = print_d,
[s] = print_s,
[f] = print_f,
[lld] = print_lld,
[time] = print_time
};
print_functions[o->type](o);
}
void print_d(struct object *o) { printf("%d", o->instance.d); }
void print_s(struct object *o) { printf("%s", o->instance.s); }
void print_f(struct object *o) { printf("%f", o->instance.f); }
void print_lld(struct object *o) { printf("%lld", o->instance.lld); }
void print_time(struct object *o) { printf("%s", o->instance.time); }
#endif
int main(void) {
struct object o = { .type = d, /* type: int */
.instance = { .d = 42 } /* value: 42 */ };
print_object(&o);
return 0;
}
You can print the pointer itself with something like %p but, if you want to print what it points to, you need to tell it what it is:
printf ("%d", *((int*)myVoidPtr));
You're not allowed to dereference a void * simply because the compiler doesn't know what it points to.
Think about it this way : Any pointer simply points to a single memory location.But the type of the pointer determines how many bytes after that to interpret/consider.If it is char* then (depending on system) 1 byte is interpreted,if it is an int* 4 bytes are interpreted, and so on.But a void* had no type.So you can't dereference a void pointer in C due to this simple reason.But you can print out the address it points to using the %p format specifier in printf() and passing that void pointer as argument.
printf("The address pointed by void pointer is %p",void_ptr); //Correct
printf("The address pointed by void pointer is %p",(void*)int_ptr);//Correct
assuming int_ptr is an integer pointer,say,and void_ptr is a void pointer.
printf("Value at address pointed by void pointer is %d",*void_ptr);// Wrong
printf("Value at address pointed by void pointer is %d",*(void*)int_ptr);//Wrong
It is not clear what your real goal is. Yes, there are ways to print data type dependent. Basically the idea is to create your own print function.
But only supplying the pointer will not be enough. In any case you need to supply pointer and the type of it.
Lets assume we have a function myprint:
myprint("%m %m %m %i", TYPE_INT, &i, TYPE_FLOAT, &f, TYPE_STRING, foo, 10);
would be a possible call. myprint is a varargs function then which needs to reconstruct the format string and arguments and then can call real printf.
If you use heap variables only, the type of the variable can be stored together with the data with some tricks (hint: check how malloc stores the block size). This would make the additional arguments superflous.
There are other solutions to that, but a good suggestion is not possible without knowledge of your real goal and the exact conditions.
I think the printf and its friends (fprintf, etc.) can dereference only char* which will be interpreted as a c-string.
Actually you can write such function yourself, because you will tell your function how to dereference void* with format flags.
Also you can add to the formats as a third value a pointer to required dereference function that will take as argument a void* and will return the value instead of pointer.
So you will need to write a function for each of the types you use in your formats and assign each function to each format properly.

Resources