I'm making a program in C. Basically I have a struct that contains some fields, and an array of pointers. Each struct has an pointer array that points to another struct forming a "connection" between them. I'm trying to get the value of a field that is stored at the memory address the pointer that is pointing at it.
Suppose this. I have two of these nodes in memory. A and B. A has a pointer inside A's array that is a reference to B. To get this pointer I'd have to do something like this:
*temp_ptr = (*ptr).pointer_array[0]
This would get the pointer address *ptr and give it to *temp_ptr.
Now what I am wondering is this. How can i do this? When I try this, I get "Expression must have struct or union type"
When I try this in lets say Java I could do this
int variable = field[0].fieldIWantToGet
I'd get the desired outcome.
Heres an image to clarify the intended behaviour that I'm trying to get. Link to behavior
Where Struct A is in a "global" collection of structs and has a array of pointers that lead to other Structs, such as B
Here is some code from my project.
#define GLOBAL_PTR_ARRAY_SIZE 10
Node* global_node_array[10];
typedef struct Node{
unsigned char node_id;
int *ptr_array[10];
int ptr_array_size;
}Node;
void append_connection(short position, short destination) {
Node* position_ptr = global_node_array[position];
Node* destination_ptr = global_node_array[destination];
if ((*position_ptr).ptr_array_size < GLOBAL_PTR_ARRAY_SIZE) {
int current_ptr_array_size = (*position_ptr).ptr_array_size;
(*position_ptr).ptr_array[current_ptr_array_size] = destination_ptr;
(*position_ptr).ptr_array_size++;
}
void print_id(Node* ptr) {
node* dptr = NULL;
dptr = ptr->ptr_array[0];
pptr = (int) (*ptr).ptr_array[0];
fprintf(stdout, "%d connection to %d exists", (*ptr).node_id, dptr-
>node_id);
}
int main(int argc, char const *argv[])
{
append_connection(0,1);
print_id(global_node_array[0]);
return 0;
}
Your picture shows array of the structs not the pointers. But the example below covers both.
struct a{
int field1,field2;
}
struct b{
struct a m[10];
}
struct c{
struct a *m[10]
}
/* and usage */
struct c *x;
struct b *y;
x -> m[5].field1;
y -> m[5] -> fileld1;
Related
Aim : To create a structure of element having certain properties. Then utilize that structure type by creating it's array in another structure.
struct Element
{
int i;
int j;
int x;
};
struct Sparse
{
int r;
int c;
int n;
struct Element *ele;
ele = (struct Element *)malloc(n*sizeof(struct Element));
};
What I wish to know is that which part of the code am I not allowed to write while creating a structure.
The common way to do this is:
struct Element
{
int i;
int j;
int x;
};
struct Sparse
{
int r;
int c;
int n;
struct Element ele[0]; // Make a zero length array
};
struct Sparse* MakeNewSparse(size_t num_ele)
{
struct Sparse* sparse = malloc(sizeof(*sparse) + num_ele*sizeof(struct Element));
return sparse;
}
This works because accessing off the end of a zero-length array is totally legal in C, provided you have allocated memory there.
In this example, we allocate enough space for the struct Sparse, and then enough more contiguous space for the array of struct Element.
After that, accessing element sparse->ele[5] is totally legal.
The line
ele = (struct Element *)malloc(n*sizeof(struct Element));
should not be part of the struct definition - that's something you do at runtime, along these lines:
struct Sparse s; // create new struct Sparse instance
s.n = get_some_size();
s.ele = malloc( s.n * sizeof *s.ele ); // no need for cast
struct in c is syntactically similar with types like int, char, etc. The definition of a struct is for compiler to know how to use variable declared with that struct such as struct Sparse var;. So the definition of a struct is not actually the code itself. It will be used at compile time.
However, malloc() is a function, which will be used at runtime, so it is nonsense to put malloc() in your struct definition.
I am trying to solve a little problem from my university, but i get into trouble completing it.
The task is to write a code defining all the data structures and create a link between them using pointers and mallocs.
ASSIGNMENT :
There are 3 blocks.
1) is a static block with 2 fields, 1st field is an integer, and a second field points to another block.
2) a block with 2 fields. 1st field points to the first block and 2nd field points to the 3rd block.
3) a block with 2 fields. 1st field is an integer and 2nd field points to the first block.
I have started creating the code and making the links but i keep getting errors which i cant seem to find thier logic.
struct A;
struct B;
struct C;
typedef struct {
int element;
struct A * pointer3;
}C;
typedef struct {
struct A * pointer 1;
struct C * pointer 2;
}B;
typedef struct {
int element;
struct B * pointer 0;
}A;
int main (){
A a;
a.pointer0 = (B*)malloc(sizeof(B));
I have reached farther then that, but the problem i get is in the last line.
Gives me the error warning: assignment from incompatible pointer type
Question: What does struct A look like? Answer: Your compiler has no idea because you never defined it.
You're assuming forward-declaring a structure type, then formally declaring a typedef alias to a structure where the alias name (but not tag) is the same as the structure tag (with no name) will resolve. It won't. You have to do that yourself.
Start with simple. Get rid of the type aliases entirely. And get rid of any unnecessary forward decls as well (B and C) What would it look like?
#include <stdio.h>
#include <stdlib.h>
struct A; // fwd decl
struct C
{
int element;
struct A *pointer3; // uses fwd decl
};
struct B
{
struct A *pointer1; // uses fwd decl
struct C *pointer2; // uses prior def
};
struct A // resolves fwd decl
{
int element;
struct B *pointer0; // uses prior def
};
int main()
{
struct A a;
a.pointer0 = malloc(sizeof(struct B));
}
That works (in the most optimistic definition of the term). If you want to use typedef aliases, you can add them in now. For example, here is all three structures both tagged and aliased.
#include <stdio.h>
#include <stdlib.h>
struct A;
typedef struct A A;
typedef struct C
{
int element;
A *pointer3;
} C;
typedef struct B
{
A *pointer1;
C *pointer2;
} B;
struct A
{
int element;
B *pointer0;
};
int main()
{
A a;
a.pointer0 = malloc(sizeof(B));
}
i'm looking for creating a function in C language that allows me to receive different structures type as parameters.
For example, if I create 3 different structures
struct a{
struct datatype0{
char test1[10];
}datatype;
struct a *next;
};
struct b{
struct datatype1{
int test1;
char test2[20];
int test3;
}datatype;
struct b *next;
};
struct c{
struct datatype2{
char test1;
char test2;
float test3;
int test4;
int test5;
}datatype;
struct c *next;
};
I wanna create a function that can receives one of theese three different struct as parameter, so I can call only it for initialize first, or second or third kind of structure:
void function("---")//<-- inside the brackets i need to insert a parameter that can be struct a, or struct b or struct c.
{
//here for example I can insert the initialize function that have to work with any struct.
}
I tryed to use a union, but I saw that I have to recreate the initializing function for each kind of struct...I tryed to use void pointers, but i need to cast theese inside the function and I need to create initializing function for each kind of struct too...
Any ideas??
The long and short of it is: avoid to do this whenever possible, but know that you Can pass different structs to a single function if you really have to.
Probably the easiest way is to create a wrapper struct, that contains 2 members: a union, and a flag to let you know which struct is passed.
typedef enum {
A,
B,
C
} struct_type;
struct _wrapper {
union {
struct a A;
struct b B;
struct c C;
};
struct_type flag;
};
void my_function(struct _wrapper *data)
{
switch (data->flag)
{
case A:
struct a val = data.A;
//do stuff with A
break;
case B:
struct b val = data.B;
break;
case C:
struct c val = data.C;
//...
break;
}
}
Another option, although it's considered bad practice, and is something you'll end up regretting is to rely on the fact that the offset of the first member of any struct is guaranteed to be 0. You can cast a pointer to any struct to a pointer to its first member. If the first member of all structs is compatible, you can rely on that (at your own risk).
One way of exploiting this is to set a function pointer as first member, or an enum field that you can use as a flag to identify the struct:
struct a {
void (*common_member)();//
/** other members **/
};
struct b {
void (*common_member)();//needn't be the same name though
/** other members **/
};
Then:
void my_func(void *data)
{//void pointer
((void (*)(void *))data)(data);//cast void *data to function pointer, and pass itself as an argument
}
This can work, if the structs are properly initialized, and the members point to the correct functions, but that's too many if's to rely on really.
Using the enum as first member is slightly less risky, but still not to be recommended. It's a sort of a combination of the function pointer and union approach
void my_func(void *data)
{
//cast void * to struct_type *, dereference AFTER the cast
//because you can't dereference a void *
switch(*((struct_type *) data))
{
case A: /* stuff */ break;
case B: /* struct b */ break;
}
}
All in all, use the first approach. Do not use the function pointer members, and acknowledge the third approach for what it is: true, you don't need a wrapper struct, but it's not that much safer than the original approach (function pointers), and no less verbose than the first approach (with union).
Bottom line: structs and unions are the way to go
In part it works. But for example, if I wanna create a function like:
typedef union elemento{
struct a A;
struct b B;
struct c C;
}elemento;
void inserimentoOrdinato(elemento dausare){
struct b prova;
prova.datatype.test1 = 3;
strcpy(prova.datatype.test2,"TESTA");
prova.datatype.test3 = 200;
prova.next = (struct a*)malloc(sizeof(struct a));
dausare.B = prova;
}
I need to use "dausare.B" or "dausare.C" for the different kinds of structures. It doesn't know itseflt which part of union has to use. Am I rigth? Thank you!
The answer is generic programming and function pointer:
**void * can be a pointer to any struct
Declaration part:
typedef void *Initializer(void* obj);//since every struct has its own fields to initialize
void function(void * obj, Initializer init)
{
init(obj);
}
Usage:
void InitA(void* a_void)
{
struct a* a = (struct a*) a_void;
//init a feilds
a->next = NULL;
}
void InitB(void* b_void)
{
struct b* b = (struct b*) b_void;
//init b feilds
b->next = NULL;
}
void InitC(void* c_void)
{
struct c* c = (struct c*) c_void;
//init a feilds
c->next = NULL;
}
int main()
{
struct a a;
struct b b;
struct c c;
Init(&a,InitA);
Init(&b,InitB);
Init(&c, initC);
return 0;
}
***Keep in mind that you dont have to build a different function for each struct if they have the same fields to initialize.
I want to have two structures in C, for example:
A:
typedef struct a
{
char *text;
int something;
}A;
and B:
typedef struct b
{
char *text;
float something_else;
}B;
Now, as far as I know, it is not possible to have a function which takes a void * parameter to get the text element from both structures. Am I wrong, is this possible in standard C?
Yes you can, using casting and the fact that the text element is the first element of both structures:
void f(void *t)
{
printf("%s\n", *((char **)t));
}
int main()
{
struct a AA = {"hello",3};
struct b BB = {"world",4.0};
f(&AA);
f(&BB);
return 0;
}
Note: Passing the address of the struct means it points to the address of text. This must then still be dereferenced one more time to get at the adress of the text itself, which is then passed to printf.
Edit: a cast to (void *) in the calls to f are not necessary (casts removed).
This produces an incompatibility warning:
#include <stdlib.h>
#include <stdio.h>
typedef struct
{
int key;
int data;
struct htData_* next;
struct htData_* prev;
}htData_;
typedef struct
{
int num_entries;
struct htData_** entries;
}ht_;
ht_* new_ht(int num_entries);
int ht_add(ht_* ht_p, int key, int data);
int main()
{
int num_entries = 20;
//crate a hash table and corresponding reference
ht_* ht_p = new_ht(num_entries);
//add data to the hash table
int key = 1305;
ht_add(ht_p,key%num_entries,20);
return 0;
}
ht_* new_ht(int num_entries)
{
ht_ *ht_p;
ht_ ht;
ht.num_entries = num_entries;
ht_p = &ht;
//create an array of htData
htData_ *htDataArray;
htDataArray = (htData_*) malloc(num_entries * sizeof(htData_));
//point to the pointer that points to the first element in the array
ht.entries = &htDataArray; // WARNING HERE!!!!!!!!!!!!!!!!
return ht_p;
}
I'm trying to copy the **ptr to the struct containing a **ptr.
Update: My simplified code was not accurate so I've posted the actual code.
The problem is that struct htData_ and htData_ are not the same thing! As far as the compiler is concerned, struct htData_ doesn't exist—it's an incomplete type. htData_, on the other hand, is a typedef for an anonymous structure. For a more detailed analysis, see Difference between struct and typedef struct in C++.
So, you're getting a warning because ht.entries is declared as the type struct htData_**, but the right-hand side of that assignment has type <anonymous struct>**. To fix this, you need to define struct htData_:
typedef struct htData_
{
...
} htData_;
This line is not proper:
htData_ array[20] = htDataArray;
You cannot assign a pointer to an array.
In your edited code, here is the problematic line:
//point to the pointer that points to the first element in the array
ht.entries = &htDataArray;
Actually, syntactically it's correct, so it should not give warning. But you are doing wrong stuff here. If you want ht.entries pointing to the first element of array than you need to declare it as,
htData_* entries; // 'struct' keyword not needed ahead of declaration
and assign it as,
ht.entries = &htDataArray[0];