C Passing Complex Structures by Reference to Functions - c

I replicated the guidance provided here but continue receiving the following error for each line with a function header and prototype: 'typedef "Neuron" may not be used in an elaborated type specifier'. I researched this error and didn't find much useful content. Any help would be most appreciated.
#include <stdio.h>
#include <stdlib.h>
struct neuronHead {
int x, y, z;
neuronHead *apical[25];
neuronHead *basal[25];
neuronHead *axon[25];
int time;
} neuron;
typedef struct neuron Neuron;
void setupBrain(struct Neuron ****brain); /* brain is a 3D array of structs */
void freeBrain(struct Neuron ****brain);
int main(void) {
Neuron ***brain;
setupBrain(&brain);
freeBrain(&brain); }
void setupBrain(struct Neuron ****brain) {
/* code for malloc'ing a 3D array of structures */ }
void freeBrain(struct Neuron ****brain) {
/* code for freeing the 3D array of structures */ }
I'm running on Ubuntu 14.04 and using Nvidia's NVCC compiler to run the code on GPUs, though this shouldn't be relevant to the error at hand.

You should replace
typedef struct neuron Neuron;
with
typedef struct neuronHead Neuron;
When writing
struct neuronHead { ... } neuron;
you introduce two elements:
a compound data type named "struct neuronHead",
and a variable named "neuron" having type "struct neuronHead".
Typedefs allow to create aliases for data types:
typedef <original_type> <alias_type>;
while in your example an <original_type> (struct neuron) is not a proper type. Proper type definitions are both:
struct neuronHead { ... } neuron; /* data type AND variable were introduced */
typedef struct neuronHead Neuron; /* data type introduced */
and:
typedef struct neuronHead { ... } Neuron; /* data type AND type alias were introduced */
Sample usage of pre-defined types:
struct neuronHead n1; /* correct */
Neuron n2; /* also correct */
struct neuron n3; /* incorrect: 'neuron' is variable name! */
Thank you.

In your code, there is no struct neuron you can typedef to. In your case, neuron is a global variable of type struct neuronHead.
You need to change your code to
struct neuronHead {
int x, y, z;
struct neuronHead *apical[25];
struct neuronHead *basal[25];
struct neuronHead *axon[25];
int time;
};
typedef struct neuronHead Neuron;
or,
typedef struct neuronHead Neuron;
struct neuronHead {
int x, y, z;
Neuron *apical[25];
Neuron *basal[25];
Neuron *axon[25];
int time;
};
or,
typedef struct neuronHead {
int x, y, z;
struct neuronHead *apical[25];
struct neuronHead *basal[25];
struct neuronHead *axon[25];
int time;
} Neuron;

Consider creating an instance of an int:
int some_int;
In C, in general, the syntax is:
<type> <variable_name>
When you have written something like this:
struct Thing {
int i;
/* Other members... */
} thing;
What this actually means is: create a variable, named thing, which is of type struct Thing, and this structure is defined as follows: { int i; /* Other members... */ }.
Then you do something like this:
typedef struct thing SomeThing;
At this point, it makes no sense, as you are trying to typedef an instance (thing).
What you probably meant was something like this:
struct Thing {
int i;
/* Other members... */
}; /* Nothing here! It's the end of type definition. */
typedef struct Thing thing; /* Typedef "struct Thing" -> "thing". */
The general syntax for typedef is:
typedef <original_type> <new_alias>
So it can be made shorter:
typedef /* Typedef the following struct... */
struct Thing {
int i;
/* Other members... */
}
thing; /* ... to such a name. */
Then you can correctly use thing as a variable type.
Also: There are no references in C, just the pointers.

Related

sizeof typedef pointer

I have a struct that defined like that:
typedef struct my_struct
{
int numbers[10];
}
*my_struct;
Is there a way to find out its size?
sizeof(my_struct);// return size of a pointer
The struct type itself is spelled with struct, so you can say:
sizeof (struct my_struct)
This would not work if you hadn't also given your struct a name, which would have been possible:
typedef struct { int numbers[10]; } * foo; /* struct type has no name */
foo p = malloc(1000);
p->numbers[3] = 81;
I'd say all of this is poor code that is needlessly terse for no reason. I would just keep all the names unique, and name everything, and not alias pointers, for that matter. For example:
typedef struct my_struct_s my_struct;
my_struct * create_my_struct(void);
void destroy_my_struct(my_struct * p);
struct my_struct_s
{
int numbers[10];
};
Everything has a unique name, the typedef is separate from the struct definition, and pointers are explicit.

Access struct in struct

I am working on a tree algorithm. These are the structures in my program:
typedef struct{
double m;
double x[DIM];
double v[DIM];
} Particle;
typedef struct{
double lower[DIM];
double upper[DIM];
} Box;
typedef struct Node{
Particle p;
Box box;
struct Node *son[4];
} Node;
Now I have written a function myFunctA() which is given by:
void myFunctA(Particle *p, Node *t){
int b=soNum(&t->box, &t->son->box, p); // Why does "&t->son->box" not work?
// do stuff ...
}
Within function myFunctA() I want to pass the box of t and the box of the son of t to the function soNum(). soNum() is given by
int soNum(Box *box, Box *sonbox, Particle *p){
// do stuff ...
}
I am trying to do this by using &t->son->box which does not work. I also tried (&t->son)->box. The error I get is always:
error: request for member ‘box’ in something not a structure or union
int b=soNum(&t->box, &t->son->box, p);
I think this is easy, but I am still quite new to C and find it somehow difficult to see it. I hope someone can help me!
Operator -> applies to a pointer, not to a struct. t is a pointer so t->son is correct. However, son is not a pointer, it is an array of pointers. Therefore
t->son->box
needs to be
t->son[someIndex]->box
where someIndex is an expression evaluating to an int between zero and three, inclusive.
t->son->box needs to be something like t->son[INDEX]->box (son is an array of node pointers).
This compiles:
#define DIM 3
typedef struct{
double m;
double x[DIM];
double v[DIM];
} Particle;
typedef struct{
double lower[DIM];
double upper[DIM];
} Box;
typedef struct Node{
Particle p;
Box box;
struct Node *son[4];
} Node;
int soNum(Box *box, Box *sonbox, Particle *p){
// do stuff ...
return 0;
}
void myFunctA(Particle *p, Node *t){
int b=soNum(&t->box, &t->son[0]->box, p); // Why does "&t->son->box" not work?
// do stuff ...
}

Nested linked lists in C

I'm trying to implement a nested linked list in C, that will be used for a hierarchical menu. However, the GCC (v4.9.3-1) is complaining to nested structures, and I have no idea how to fix this. Here is the minimum (non)working example.
Is this nesting even possible in C?
main.c
#include "menu.h"
int main(void) {
Init_Menu();
return 0;
}
menu.c
#include "menu.h"
MenuItem_t LVL_0_MainMenu = {
.size = 0,
};
MenuItem_t LVL_1_Measurements = {
.size = 0,
};
void Init_Menu(void) {
Menu_Add_Child(&LVL_0_MainMenu, &LVL_1_Measurements);
}
void Menu_Add_Child(MenuItem_t *parent, MenuItem_t *child) {
parent->children[parent->size] = child;
child->parent = parent;
parent->size++;
}
menu.h
typedef struct {
unsigned char size;
MenuItem_t children[10];
MenuItem_t *parent;
} MenuItem_t;
extern MenuItem_t LVL_0_MainMenu;
extern MenuItem_t LVL_1_Measurements;
void Init_Menu(void);
void Menu_Add_Child(MenuItem_t *parent, MenuItem_t *child);
Based on answers by #bolov and #sps (once again, thanks to both of them), here is the minimum working example:
main.c
#include "menu.h"
int main(void) {
Init_Menu();
return 0;
}
menu.c
#include "menu.h"
MenuItem_t LVL_0_MainMenu = {
.size = 0,
};
MenuItem_t LVL_1_Measurements = {
.size = 0,
};
void Init_Menu(void) {
Menu_Add_Child(&LVL_0_MainMenu, &LVL_1_Measurements);
}
void Menu_Add_Child(MenuItem_t *parent, MenuItem_t *child) {
parent->children[parent->size] = child;
child->parent = parent;
parent->size++;
}
menu.h
struct MenuItem_t {
unsigned char size;
struct MenuItem_t *children[10];
struct MenuItem_t *parent;
};
typedef struct MenuItem_t MenuItem_t;
extern MenuItem_t LVL_0_MainMenu;
extern MenuItem_t LVL_1_Measurements;
void Init_Menu(void);
void Menu_Add_Child(MenuItem_t *parent, MenuItem_t *child);
The difference between this corrected program and the original (non)working program, is that the children array is defined as an array of pointers to variables of the type MenuItem_t instead of the array of variables of the same type. The other difference is that a nested list (inside the structure) should also contain the keyword struct as #bolov explained.
You need to use struct for the type used inside itself, even if you typedef it later on.
E.g. this won't work:
struct X_ {
X* next;
};
typedef struct X_ X;
But this will
struct X_ {
struct X_* next;
};
As a side note, I really don't like this form:
typedef struct {
} X;
I use:
struct X {
};
typedef struct X X;
But maybe this is just me being more fond of C++.
If you want to use that form, it's the same: you need to add struct and it works:
typedef struct {
struct X2* next;
} X2;
regarding:
struct X {
struct X arr[10];
};
You can't have that! The array is just in our way to understand why. So let's simplify:
struct X {
int a;
struct X var;
};
This can't be. What size would X be? sizeof(X) = sizeof(int) + sizeof(X) + padding. Do you see the problem? All you can do is have a pointer to X, but not an object X inside X.
Returning to your array. You need dynamic arrays:
struct X {
struct X* arr;
int arr_size;
};
It gets more complicated as you need to manage the memory (malloc/free fun), but you can't avoid it.
First of all, you cannot do,
typedef struct {
SomeName_t some_var;
} SomeName_t;
You need to do,
typedef struct somename {
struct somename some_var;
} SomeName_t;
Also, a struct cannot have a member which is an array of structure itself. However, a struct can have a member which is an array of pointer to the same structure.
struct foo {
struct foo foo_arr[10]; /* Will give error */
struct foo *foo_ptr_arr[10]; /* Legal */
};
However, I dont see a reason that your children member should be an array of struct anyways. Because, as can be seen in menu.c, you are doing
parent->children[parent->size] = child;
where the type of child is MenuItem_t *. So I think you basically wanted MenuItem_t.children to be an array of MenuItem_t *, and not an array of MenuItem_t.
So making this change should resolve your issue:
menu.h
typedef struct menuitem {
unsigned char size;
/* MenuItem_t children[10]; */ /* Not possible */
struct menuitem *children[10]; /* This is what you want to do */
struct menutem *parent;
} MenuItem_t;

Is it possible to do inheritance from an abstract/base struct or simulate something along those lines in C?

I am currently working with a C program that uses structs composed of xyz coordinates, but sometimes these coordinate may refer to vectors (Force/velocity type, not the data structure) while at other times it may be referring to position. I know its possible to simply use one struct for all of these different conditions since they all use mostly the same data type (float), but to simply keep my math better organized (plus variable and struct names) and keep things from getting mixed up, is there a way to define a base struct that defines itself as having three floats, be inherited by another struct that more specifically defines what the struct is supposed to be (such as position instead of velocity, etc. etc.)? I know C is not OOP, but it seems like it could be possible to do this Here is what the base struct would be like:
struct ThreeDCartesianData
{
float x;
float y;
float z;
};
A more specific struct would inherit from that and perhaps define extra variables, or use different names for the variables. There will be multiple position structs being used, but I think only one velocity struct for each set of data. I have seen similar questions to this, but they all seem to be referring to a higher level language (C++, C#, etc. etc.)
You can use a union for this. Your main struct would contain a union of the "derived" structs as well as a "flag" field telling you which member of the union is valid:
enum { DERIVED11, DERIVED2, DERIVED3 };
struct derived1 { int x1; };
struct derived2 { char x2; };
struct derived3 { float x3; };
struct ThreeDCartesianData
{
float x;
float y;
float z;
int derivedType;
union {
struct derived1 d1;
struct derived2 d2;
struct derived3 d3;
} derived;
};
Then you can use them like this:
struct ThreeDCartesianData data1;
data1.x=0;
data1.y=0;
data1.z=0;
data1.derivedType = DERIVED1;
data1.derived.d1.x1 = 4;
You could alternately define them like this:
struct common
{
int type;
float x;
float y;
float z;
};
struct derived1
{
int type;
float x;
float y;
float z;
int x1;
};
struct derived2
{
int type;
float x;
float y;
float z;
char x2;
};
struct derived3
{
int type;
float x;
float y;
float z;
float x3;
};
union ThreeDCartesianData {
struct common c;
struct derived1 d1;
struct derived2 d2;
struct derived3 d3;
};
And use them like this:
union ThreeDCartesianData data1;
data1.c.type=DERIVED1;
data1.d1.x=0;
data1.d1.y=0;
data1.d1.z=0;
data1.d1.x1 = 4;
If all the structs in a union have an initial list elements of the same type in the same order, the standard allows you to access those fields from any of the sub-structs safely.
What about using typedefs?
typedef struct general3d {
float x;
float y;
float z;
} general3d_t;
typedef general3d position;
typedef general3d velocity;
This way, when you come across something that's a velocity type, you encode that into the variable type, but under the hood, it's still just 3 points, x, y, z. Then, readers of the code will know you're talking about a velocity and not a position. If you want to get really crazy with it, you hide general3d away in some implementation file, so a user can never instantiate a general3d on their own, since they should be using either position or velocity as the situation requires; this may or may not be reasonable for your task at hand/worth the extra effort.
EDIT: I'm not positive about variable-renaming or about adding more variables directly to the same struct, but I would start to head in the direction of a different design at that point.
On the one hand, if you have two structs that have the same underlying types but require different names, you probably just have two separate structs. For example:
struct point3d {
float x;
float y;
float z;
};
struct person {
float age;
float weight;
float salary;
};
Yes, those are both 3 floats, but their understanding is very different, and they should be able to vary on their own if one or the other changes. Perhaps I want to add a name field to the person, but there's no reasonable analogue for a char * on point3d. Just define them separately if they mean different things.
As for adding more variables, that sounds like structs that contain other structs:
struct point3d {
float x;
float y;
float z;
};
struct person {
point3d position;
float age;
float weight;
float salary;
};
// access like:
person.position.x;
I've done this sort of thing before. I embed a copy of the base type at the front of the derived type struct. This more closely mimics what c++ might do. Here are two methods I've used.
Using simple type:
#define XYZDEF \
int type; \
float x; \
float y; \
float z
// base type
struct xyzdata {
XYZDEF;
};
// derived type 1
struct vector {
XYZDEF;
int vector_info;
...
};
// derived type 2
struct position {
XYZDEF;
int position_info;
...
};
#define BASEOF(_ptr) \
((struct xyzdata *) (_ptr))
// vector_rotate -- rotate a vector
void
vector_rotate(vector *ptr)
{
}
// position_rotate -- rotate a position
void
position_rotate(position *ptr)
{
}
// xyzrotate -- rotate
void
xyzrotate(xyzdata *ptr)
{
switch (ptr->type) {
case TYPE_POSITION:
vector_rotate((vector *) ptr);
break;
case TYPE_VECTOR:
position_rotate((position *) ptr);
break;
}
}
Using a virtual function table pointer:
#define XYZDEF \
int type; \
vtbl *vtbl; \
float x; \
float y; \
float z
// forward definitions
struct xyzdata;
struct vector;
struct position;
// virtual function table
struct vtbl {
void (*rotate)(struct xyzdata *);
};
// base type
struct xyzdata {
XYZDEF;
};
// derived type 1
struct vector {
XYZDEF;
int vector_info;
...
};
// derived type 2
struct position {
XYZDEF;
int position_info;
...
};
#define BASEOF(_ptr) \
((struct xyzdata *) (_ptr))
// vector_rotate -- rotate a vector
void
vector_rotate(struct xyzdata *ptr)
{
struct vector *vec = (void *) ptr;
...
}
// position_rotate -- rotate a position
void
position_rotate(struct xyzdata *ptr)
{
struct position *pos = (void *) ptr;
...
}
// xyzrotate -- rotate
void
xyzrotate(xyzdata *ptr)
{
ptr->vtbl->rotate(ptr);
}

error: dereferencing pointer to incomplete type

Looked through many other SO posts related to this, but none were able to help me. So, I have the following structs defined:
typedef struct
{
int created;
double data;
int timeLeft;
int destination;
}dataPacket;
typedef struct
{
dataPacket *array;
int currIndex;
int firstIndex;
int nextTick;
int maxLength;
int length;
int stime;
int total;
}packetBuffer;
typedef struct{
int mac;
struct wire *lconnection;
struct wire *rconnection;
int numRecieved;
struct packetBuffer *buffer;
int i;
int backoff;
}node;
typedef struct{
float length;
float speed;
int busy;
struct dataPacket *currPacket;
struct node *lnode;
struct node *rnode;
}wire;
And then I'm trying to use the following function:
int sendPacket(node *n, int tick)
{
if(n->buffer->length > 0)
{
if(n->backoff <= 0)
{
if (n->lconnection->busy != 0 || n->lconnection->busy != 0)
{
n->i++;
n->backoff = (512/W * genrand()*(pow(2,n->i)-1))/TICK_LENGTH;
}
else
{
n->lconnection->busy = 1;
n->rconnection->busy = 1;
n->lconnection->currPacket = n->buffer[n->buffer->currIndex];
n->rconnection->currPacket = n->buffer[n->buffer->currIndex];
}
}
else
{
n->backoff--;
}
}
}
I'm getting the error described in the title everytime I try to access a member of buffer, lconnection, or rconnection.
struct packetBuffer *buffer;
You've defined a type packetBuffer (a typedef for an otherwise anonymous struct).
You haven't defined struct packetBuffer.
In the absence of an existing type struct packetBuffer, the compiler treats it as an incomplete type, assuming that you'll complete it later. The declaration
struct packetBuffer *buffer;
is perfectly legal, but you can't dereference buffer unless the type struct packetBuffer is visible.
Just drop the struct keyword.
(My personal preference is to drop the typedef and consistently refer to struct types as struct whatever, but that's a matter of style and taste.)
The following:
typedef struct {
int x;
char *y;
...
} my_struct;
creates an identifier for an anonymous structure. In order, for a structure to refer to an instance of itself, it must not be "anonymous":
typedef struct my_struct {
int x;
char *y;
struct my_struct *link
....
} my_struct_t;
This means that my_struct_t is now the type struct my_struct and not just an anonymous struct. Also, note that struct my_struct can be used within its own structure definition. That is not possible with anonymous structs.
As a final complication, the my_struct in struct my_struct is in a differenct "namespace" than the my_struct_t. This is sometimes used to to simplify (or confuse) things in code like this:
typedef struct my_struct {
int x;
char *y;
struct my_struct *link
....
} my_struct;
Now I can use my_struct anywhere in my code instead of struct my_struct.
Finally, you could separate the typedef from the structure definition to achieve the same effect:
struct my_struct {
int x;
char *y;
struct my_struct *link;
....
};
typedef struct my_struct my_struct;
As noted in David R.Hanson's C Interfaces and Implementations, "This definition is legal because structure, union, and enumeration tags occupy a same name space that is separate from the space for variables, functions, and type names."

Resources