I'm having trouble passing an array of structs to a function in C.
I've created the struct like this in main:
int main()
{
struct Items
{
char code[10];
char description[30];
int stock;
};
struct Items MyItems[10];
}
I then access it like: MyItems[0].stock = 10; etc.
I want to pass it to a function like so:
ReadFile(MyItems);
The function should read the array, and be able to edit it. Then I should be able to access the same array from other functions.
I've tried heaps of declarations but none of them work.
e.g.
void ReadFile(struct Items[10])
I've had a look around for other questions, but the thing is they're all done different, with typedefs and asterisks. My teacher hasn't taught us pointers yet, so I'd like to do it with what I know.
Any ideas? :S
EDIT: Salvatore's answer is working after I fixed my prototype to:
void ReadFile(struct Items[10]);
struct Items
{
char code[10];
char description[30];
int stock;
};
void ReadFile(struct Items items[10])
{
...
}
void xxx()
{
struct Items MyItems[10];
ReadFile(MyItems);
}
This in my compiler works well.
What compiler are you using? What error you got?
Remember to declare your struct before your functions or it will never work.
Define struct Items outside of main. When passing an array to a function in C, you should also pass in the length of the array, since there's no way of the function knowing how many elements are in that array (unless it's guaranteed to be a fixed value).
As Salvatore mentioned, you also have to declare (not necessarily define) any structs, functions, etc. before you can use them. You'd usually have your structs and function prototypes in a header file in a larger project.
The below is a working modification of your example:
#include <stdio.h>
struct Items
{
char code[10];
char description[30];
int stock;
};
void ReadFile(struct Items items[], size_t len)
{
/* Do the reading... eg. */
items[0].stock = 10;
}
int main(void)
{
struct Items MyItems[10];
ReadFile(MyItems, sizeof(MyItems) / sizeof(*MyItems));
return 0;
}
The function won't know that the type struct Items exists if you declare it only locally inside the main function body scope. So you should define the struct outside:
struct Item { /* ... */ };
void ReadFile(struct Items[]); /* or "struct Item *", same difference */
int main(void)
{
struct Item my_items[10];
ReadFile(my_items);
}
This is dangerous of course since ReadFile has no idea how big the array is (arrays are always passed by decay-to-pointer). So you would typically add this information:
void ReadFile(struct Items * arr, size_t len);
ReadFile(my_items, 10);
Instead of your declaration, declare in that way:
typedef struct {
char code[10];
char description[30];
int stock;
}Items;
and the function like that:
void ReadFile(Items *items);
With typedef you define a new type, so you don't need to use word "struct" each time.
You pretty much have to use pointers for this. You function would look like this:
void ReadFile(Items * myItems, int numberOfItems) {
}
You need to use pointer to array, after that its easy to access its members
void ReadFile(Items * items);
should work.
Well, when you pass a structure like you did, it actually creates a local copy of it in the function. So it will have no effect on your original structure, no matter how you modify it in ReadFile.
I am not sure about a different approach and this might not answer your question, but I recommend you try pointers. You'll definitely be using them quite a lot in C/C++. And they can be really powerful once you master them
Have you tried to declare you function like this:
void ReadFile(struct Items[])
Might be helpful:
http://www.daniweb.com/software-development/cpp/threads/105699
Why dont you use pass the pointer to the array to the methods that need it?
If you want the same struct array then you should use pointer to the array and not pass as array as that will create a copy.
void ReadFile(struct Items * items);
and where you call it
struct Items myItems[10];
ReadFile(myItems);
Need to be careful with pointers...
Related
I've those two structs :
typedef struct
{
char* name;
int flightCount;
Flight** flightArr;
LIST dateList;
int flightsSorted;
}Airline;
typedef struct
{
Airport* airportsArr;
int airportsCount;
}AirportManager;
and I need to write a general printer for both arrays (one is struct array and the other is pointer array).
I know that general printer should look like that:
void generalArrayFunction(const void* pArr, const int size, int sizeOfElement, void(*printer)(const void*))
{
for(int i=0;i<size;i++)
printer((char*)pArr + i * sizeOfElement);
}
and it's work great with the regular array which I print with the following line:
generalArrayFunction(manager.airportsArr,manager.airportsCount,sizeof(manager.airportsArr[0]),printAirport);
but with the pointer array I can't use the same logic and I dont know what should I do.the following line prints one struct but the second one messed up.
generalArrayFunction(*pComp->flightArr, pComp->flightCount, sizeof(pComp->flightArr[0]), printFlight);
any suggestions ?
If i got your intention right, In this code:
generalArrayFunction(*pComp->flightArr, pComp->flightCount, sizeof(pComp->flightArr[0]), printFlight);
sizeOfElement will be the size of a pointer because it's an array of pointers, you need to make another dereference to reach the struct and get the size, that's why the first struct is printing ok and the subsequent are not.
Try this:
generalArrayFunction(*pComp->flightArr, pComp->flightCount, sizeof((*pComp->flightArr)[0]), printFlight)
I declared a struct like this one :
typedef struct s_data {
char buff[2048];
int len;
void *func[10];
struct data *next;
} t_data;
In my code, when passing a *data, I assigned some functions (just giving one so it is more understandable)
void init_data(t_data *data)
{
data->len = 0;
data->func[0] = &myfirstfunctions;
//doing the same for 9 others
}
My first function would be something taking as argument *data, and an int.
Then, I try to use this function in another function, doing
data->func[0](data, var);
I tried this and a couple of other syntaxes involving trying to adress (*func[0]) but none of them work. I kind of understood from other much more complex questions over there that I shouldn't store my function like this, or should cast it in another typedef, but I did not really understand everything as I am kind of new in programming.
void* can only be used reliably as a generic object pointer ("pointer to variables"). Not as a generic function pointer.
You can however convert between different function pointer types safely, as long as you only call the actual function with the correct type. So it is possible to do just use any function pointer type as the generic one, like this:
void (*func[10])(void);
...
func[0] = ((void)(*)(void))&myfirstfunction;
...
((whatever)func[0]) (arguments); // call the function
As you might note, the function pointer syntax in C is horrible. So I'd recommend using typedefs:
typedef void genfunc_t (void);
typedef int somefunc_t (whatever*); // assuming this is the type of myfirstfunction
Then the code turns far easier to read and write:
genfunc_t* func [10];
...
func[0] = (genfunc_t*)&myfirstfunction;
...
((somefunc_t*)func[0]) (arguments);
If all of your functions will have the same signature, you can do this like:
#include <stdio.h>
typedef void (*func)(void *, int);
struct s_data {
char buff[2048];
int len;
func f[10];
struct s_data *next;
};
static void
my_first_function(void *d, int x)
{
(void)d;
printf("%d\n", x + 2);
}
static void
init_data(struct s_data *data)
{
data->len = 1;
data->f[0] = my_first_function;
}
int
main(void)
{
struct s_data d;
init_data(&d);
d.f[0](NULL, 5);
return 0;
}
If your functions have different signatures, you will want to either use a union, or perhaps you will need several different members of the struct to store the function pointers.
The problem is that you haven't actually declared an array of function pointers. What you actually did is an array of pointers to void.
The syntax of declaring a pointer to function is as following:
function_return_type (*pointer_name)(arg1_type,arg2_type,...);
Then you can create an array of pointers to functions:
function_return_type (*arr_name[])(arg1_type, arg2_type,...)
Therefore, the declaration of your structure should look like this:
typedef void (*pointer_to_function)(void *, int);
struct s_data {
char buff[2048];
int len;
pointer_to_function array_of_pointeters[10];
struct s_data *next;
};
Good luck:)
So I am still pretty new to C programming. I have learned Python though, so I am familliar to some of the codes.
For instance when I create a function in python, I am able to make it general and usable for different classes.
I want to do something similar here. I have two structs which look practically the same. I want to use the same function for both structs, but ofcourse I cant send in the struct name as an argument into the function. What do I do instead?
For now dont worry about what the function does. Its the principle of being able to use two structs in the same function that counts for me. If this is a totally wrong perspective, then I am sorry but this was my first thought when coming upon this problem.
typedef struct{
int number;
struct node *next;
}struct_1;
struct node *head;
typedef struct{
int number;
struct node *next;
}struct_2;
void main()
{
int number1 = 10;
int number2 = 20;
function(number1);
function(number2);
}
void function(int x, struct) // Here is where I want to be able to use 2 different structs for the same function
{
struct *curr, *head;
curr=(node1*)malloc(sizeof(node1));
printf("%d", curr->number);
}
You could have two instances of one structure.
The function can accept either instance and process it as needed.
typedef struct{
int number;
struct node *next;
}mystruct;
void function(int x, mystruct *eachstruct);//prototype
int main()
{
int number1 = 10;
int number2 = 20;
//declare two instances of mystruct
mystruct list_1 = { 0, NULL};
mystruct list_2 = { 0, NULL};
// call the function with one or the other instance of mystruct
function(number1, &list_1);
function(number2, &list_2);
}
void function(int x, mystruct *eachstruct)
{
//do stuff in function
eachstruct->number = x;
if ( eachstruct->next == NULL)
{
//do more stuff
}
}
C does not use duck typing as Python does so you cannot pass one structure that looks like other, completely unrelated structure as if it was this other structure.
Unfortunately C cannot do what you want.
Your options are:
Refactor the code to use the same struct type for all items.
Pass the fields of interest in the structs directly to the functions
Write code to marshal the similar structs to a common struct.
Play fast and loose with the type system and arrange shared elements the same way in the two different structs and cast your pointers.
If you just want a linked list check out how code re-use is achieved in the linux kernel
Answer: No, you cannot do it directly. Welcome to static typing.
There is a way to achieve something similar by using our beloved void * and some castings but, believe me, it is not what you want to do. If you really want to do it ask directly for it. You have been warned.
typedef struct
{
char struct_variable_1a[10];
char struct_variable_1b[12];
} struct1;
typedef struct
{
char struct_variable_1a[10];
char struct_variable_1b[12];
int struct_variable_2c;
} struct2;
typedef struct1 *struct1_ptr;
typedef struct2 *struct2_ptr;
static void sampleFunction(struct1_ptr valueToInsert){
//this code does some stuff here
}
int main(){
struct1_ptr struct1_var = (struct1_ptr) malloc(sizeof(struct1));
strcpy(struct1_var->struct_variable_1a, "some value");
strcpy(struct1_var->struct_variable_1b, "some value");
sampleFunction(struct1_var);
return 0;
}
I have a sample code in C programming as shown above. In the main method, I am trying to pass a variable of type struct1_ptr for sampleFunction method call.
This works like a charm. But when I want to pass a variable of type struct2_ptr, the compiler is throwing error. Basically, I am java developer. I want to reuse this sampleFunction method for any variable type in its parameter in general. Kindly help me in this.
You could emulate inheritance in C like this:
typedef struct
{
char struct_variable_1a[10];
char struct_variable_1b[12];
} struct1;
typedef struct
{
struct1 parent; /* Must be first element! */
int struct_variable_2c;
} struct2;
And then call like this:
sampleFunction((struct1_ptr)ptr_to_struct2);
or (I would favor this, because there's no cast):
sampleFunction(&ptr_to_struct2->parent);
Just note that you won't be able to access members of struct2 in function without casting it back.
These work for simple structures, but if you do anything more complex, using C++ would be more approriate.
unfortunately C does not support method overloading / polymorphism. So you have to write your own methodology.
one is, to give the type as a first parameter to every overloaded function. Inside the function you walk along with a simple switch-case to jump to the original function implementation (like struct1_sampleFunction() and struct2_sampleFunction()).
another is, to put an RECORDCORE struct at the beginning of every struct and fill the type into this RECORDCORE, so each function can dispatch according to this data.
in both cases you have to change the prototype from "struct1_ptr value" to "void *value"
change your function from:
static void sampleFunction(struct1_ptr valueToInsert){
//this code does some stuff here
}
to:
static void sampleFunction(void* valueToInsert){
//this code does some stuff here
}
If you want to identify the type of the structure add a second parameter to your function that contains the size of the struct.
//Edit:
Inside the function you have to cast your variable back to the structure you want to use. for example:
strcpy(((struct1_ptr)valueToInsert)->struct_variable_1a, "some value");
I listed some example code below and the question is if there is a way for the function_name to access the value of number from struct_name?
typedef struct struct_name {
int number
void (*func)();
} * struct_name_ptr;
void function_name() {
//access number from struct
}
main() {
struct_name_ptr newobject;
newobject->func=&function_name;
newobject->func(); //can it print the value of the number in the structure above?
}
Uh - no.
A struct can certainly contain a function pointer. But the function you call wouldn't have any knowledge of the struct. Unless you passed a pointer as a function argument, or made the struct global.
With my limited knowledge of programming, I don't think this is possible. Though the struct contains a function pointer, the address of the function assigned to it is different and I don't think there will be anyway for it to access it unless you pass it as an argument.
Well, two things, struct_name->number should have a value, and it either needs to be in the same scope as &function_name or it needs to be explicitly passed. Two ways to do it:
/* Here is with a global calling struct */
#include<stdio.h>
typedef struct struct_name {
int number;
void (*func)();
} * struct_name_ptr;
struct struct_name newobject = { 0 };
void function_name() {
printf("%d",struct_name);
}
void main() {
struct struct_name_ptr newobject;
newobject->func=&function_name;
newobject->func();
}
/* And one with a modified function_name */
#include<stdio.h>
typedef struct struct_name {
int number;
void (*func)();
} * struct_name_ptr;
void function_name(struct_name) {
printf("%d",struct_name);
}
void main() {
struct struct_name_ptr newobject;
newobject.number = 0;
newobject->func=&function_name;
newobject->func(newobject);
}
No, a pizza won't ever know what the pizza delivery guy, who delivered it, looks like.
A regular function is just an address in memory. It can be called using a function pointer like in this case. In any case: The function won't know how it was called. In particular it won't know that it was called using a function pointer that's part of (a piece of memory corresponding to) some struct.
When using a language with classes like C++, member functions will have a hidden argument which is a pointer to the class instance. That's how member functions know about their data.
You can 'simulate' a simple OOP in plain C, for your example like:
typedef struct {
int number;
void (*func)();
} class;
void function_name(class *this) {
printf("%d",this->number);
}
#define CALL(c,f) c.f(&c)
int main() {
class object={12345,function_name};
CALL(object,func); // voilá
}