Pointer in typedef struct confusion - c

I am trying to define a typedef struct as follows:
typedef struct node{
int keys[2*MIN_DEGREE-1];
struct node* child[2*MIN_DEGREE];
int numkeys;
int isleaf;
} BNODE,*BNODEPTR;
Instead of using struct node* child[2*MIN_DEGREE] why can't I declare the struct as follows:
typedef struct node{
int keys[2*MIN_DEGREE-1];
BNODEPTR child[2*MIN_DEGREE];
int numkeys;
int isleaf;
} BNODE,*BNODEPTR;
I am little confused as to how the compiler resolves structs that has nested pointers to the same type. It will be great somebody helps me clear this up.
Thanks

You can't use BNODEPTR in the body of the structure like that because it either doesn't exist as a type at all until after the definition after the close brace of the structure body, or (worse) it refers to a different type altogether*.
You could use:
typedef struct node BNODE, *BNODEPTR;
struct node
{
int keys[2*MIN_DEGREE-1];
BNODEPTR child[2*MIN_DEGREE];
int numkeys;
int isleaf;
};
And there's another whole argument that says BNODEPTR is evil and you should only use BNODE and BNODE *, but that's a style issue, not a technical one.
Were it my code, it would probably be more like:
typedef struct Node Node;
struct Node
{
int keys[2*MIN_DEGREE-1];
Node *child[2*MIN_DEGREE];
int numkeys;
int isleaf;
};
In C++, the rules are slightly different and you would not need the typedef line (so Node would be known as a type from the open brace).
* This can only happen if the original BNODEPTR is defined at an outer scope and this one appears inside a function, but when it happens, it is really confusing!

Instead of using struct node* child[2*MIN_DEGREE] why can't I declare
the struct as follows: BNODEPTR child[2*MIN_DEGREE];?
At that point, compiler (yet) does not know what the symbol BNODEPTR is.

Related

Usage of Typedef Struct in C programming

I have a C template which is given me as homework. But before doing homework, I need to understand the usage of "typedef" and "struct" clearly to move on coding. Here is the code;
typedef struct NODE_s *NODE;
typedef struct NODE_s
{
NODE right;
NODE left;
unsigned long data;
int height;
} NODE_t[1];
typedef struct TREE_s *TREE;
typedef struct TREE_s
{
NODE root;
} TREE_t[1];
TREE tree_init();
NODE node_init(unsigned long data);
First of all, what is the line typedef struct NODE_s *NODE; is doing here? Why it is named like a pointer with a *?
Then, after the struct definition, what is the purpose of creating a variable named NODE_t[1], is the square brackets with the number "1" something connected with an array, or it is just something else?
Lastly, when the tree_init(); and node_init(unsigned long data); functions are declared, why the TREE and NODE datatype names are used to the contrary they were declared as *TREE and *NODE before the struct definitions? Thank you for the answers.
The template you were given is this, where I've added numbers to some of the lines for ease of reference:
typedef struct NODE_s *NODE; // 1
typedef struct NODE_s // 2
{
NODE right; // 3
NODE left;
unsigned long data;
int height;
} NODE_t[1]; // 4
typedef struct TREE_s *TREE;
typedef struct TREE_s
{
NODE root;
} TREE_t[1];
TREE tree_init(); // 5
NODE node_init(unsigned long data);
What are the problems here?
As noted in comments, the SO Q&A Is it a good idea to typedef pointers suggests that it is not a good idea to typedef pointers, with limited exceptions for 'pointers to functions' (not relevant here) and perhaps (but probably not) for opaque types. This line does two things: (1) it says "there is a structure type with the tag NODE_s; (2) the name NODE is a synonym for struct NODE_s *. The structure type is incomplete at the moment; no details are known about its members.
This line starts a new typedef, but also starts the definition of the type struct NODE_s (because of the { that follows on the next line).
The type NODE is already known; it can be used here. It means the same as if you wrote struct NODE_s *right;.
The name NODE_t is an alias for the type struct NODE_s[1], an array of 1 struct NODE_s. It isn't clear what this is going to be used for. I have reservations (at best) about its existence. (You can also apply the discussion in points 1, 2, 4 to the struct TREE_s type, mutatis mutandis.)
This is a function declaration, but it is not a prototype declaration. It says that the tree_init() function can be called with any number of arguments of any type because no information is specified about the number or type of those arguments. We do know it is not a variadic function (variable argument list, like printf()) because those must have a full prototype declaration ending with , ...) in scope before they're used. If you want to specify that the function takes no arguments, say so: TREE tree_init(void);.
I think the intent behind the NODE_t and TREE_t types is to allow you to write, for example:
int main(void)
{
TREE_t x = { 0 };
if (x->root != 0)
return 1;
return 0;
}
I'm not convinced whether that's sufficiently helpful to warrant the type compared with using struct NODE_s x and using x.root in the test. It does save you from having to add an & when passing a pointer to a function; again, I'm not sure it is really sufficiently helpful to warrant its existence.
What I would prefer to see as the template is:
typedef struct NODE_s NODE;
struct NODE_s
{
NODE *right;
NODE *left;
unsigned long data;
int height;
};
typedef struct TREE_s TREE;
struct TREE_s
{
NODE *root;
};
extern TREE *tree_init(void);
extern NODE *node_init(unsigned long data);
This removes the pointers from the typedef statements, avoids the somewhat peculiar array types, and uses an explicit prototype for tree_init(). I personally prefer to have function declarations marked with extern; in a header, they'll match the extern on those rare global variables that are declared in the header. Many people prefer not to use extern because the compiler assumes that anyway — so be it; the most important thing is consistency.
The code in main() would now be written:
int main(void)
{
TREE x = { 0 };
if (x.root != 0)
return 1;
return 0;
}
The difference? An arrow -> changed to a dot .. Not a lot of problem there. However, when calling functions, you'd probably use &x whereas with the TREE_t type, you would just write x (because it's an array).

Nesting Structs in C

I'm a noob at C and need some help getting my code to...welll...do anything. I have the following put into a .h file.
typedef struct
{
int active;
int dead;
ucontext_t t;
struct node *link;
}gtthread_t;
struct node{
struct gtthread_t thread;
};
typedef struct
{
int rubic;
}gtthread_mutex_t;
This is in a .h file... a .h file where I have had to #include ucontext.h ... which I know I am also not supposed to do... but it's the only way I can access ucontext_t, I find.
So, my error here is "field thread has incomplete type".
Why? What does that even mean? And how can I possible NOT import ucontext.h if I want to declare structs with that kind of data in the .h file?
Has nothing to do with your other include. This has to do with the fact that your first struct is anonymous and has a type name gtthread_t. C unlike C++ distinguishes between gtthread_t and struct gtthread_t.
Either name the struct:
struct gtthread_t
{
int active;
int dead;
ucontext_t t;
struct node *link;
};
Or change the type name to the typedef:
struct node{
gtthread_t thread;
};
The ucontext.h header only pre-declares the ucontext_t type. You're only supposed to use pointers to it, since its size is not known. Change your code to:
ucontext_t *t;
and you will be fine. Notice that all the functions in the ucontext.h header use such pointers to refer to contexts. This is common in C API design, since it allows the representation to be hidden inside the API's implmentation, which is nice.
One problem is that struct node has not been declared yet, so the gtthread_t type cannot be completed.
typedef struct
{
int active;
int dead;
ucontext_t t;
struct node *link;
}gtthread_t;
struct node{
struct gtthread_t thread;
};
You'll need a forward declaration of struct node:
struct node;
typedef struct
{
int active;
int dead;
ucontext_t t;
struct node *link;
}gtthread_t;
struct node{
struct gtthread_t thread;
};
Try that and see if it makes a difference.

Pointer typecasting in c

I am writing an implementation of graphs in C language. I came across a situation where I am not able to figure out the reason for the way the compiler is behaving with a pointer typecast warning.
Here are the structures;
#define MAXV 10
typedef struct {
int y;
int weight;
struct edgenode *next;
} edgenode;
typedef struct {
edgenode *edge[MAXV+1];
int degree[MAXV+1];
// other info of graph
} graph;
// operation in some other function
p->next = g->edge[x];
I got a pointer typecast warning[enabled by default] when I do this kind of operation.
I was not able to remove this warning even after trying to typecast with every possible cast.
Finally I made a code change in the structure and suddenly the warning was gone.
The structure code change was this:-
typedef struct edgenode { // note that I have added structure name here
// same as above definition
} edgenode;
// operation in some other function
p->next = g->edge[x];
Now the warning is gone and code runs without any warnings.
I do not understand why is this happening; can anybody help me with this problem?
The problem is here:
typedef struct {
int y;
int weight;
struct edgenode *next;
} edgenode;
It is not clear what type struct edgenode *next; is referring to (it doesn't matter; somewhere, presumably, there's a struct edgenode defined), but it is not this structure because it has no tag. You need:
typedef struct edgenode
{
int y;
int weight;
struct edgenode *next;
} edgenode;
Now the pointer refers to another structure of this same type. So, the fix you found was the correct fix for your problem.
Remember: a typedef is an alias (alternative name) for an existing type. You created a type name edgenode, but you had not defined the type struct edgenode. You don't have to fully define a structure type before you create pointers to it; this can be a good way of creating 'opaque types'.
The other way to define things is:
typedef struct edgenode edgenode;
struct edgenode
{
int y;
int weight;
edgenode *next;
};
This says that the type name edgenode is an alias for a struct edgenode; the structure definition then tells the compiler what a struct edgenode looks like.

initialize struct in c

typedef struct Node{
int x;
int y;
struct Node* next;
}Node;
i want create in main "list" in this way:
int main(){
Node list;
}
and not in this way:
int main(){
Node list = {1,2,NULL};
}
i want initialize a struct in declaration of struct
tryed this way:
typedef struct Node{
int x;
int y;
struct Node* next;
}Node = {1,2,NULL};
error C2513: 'Node' : no variable declared before '='
need help
You can't give structure members predefined values in C. Use a constructor-like function or a constructor-like macro.
The typedef (or struct) "statement" defines a type, not an object.
Types have no value. It only makes sense to speak of values in relation to objects.
Objects do not have a default value (other than 0 when they're implicitly initialized).
So you can't do what you want.

C: pointer to struct in the struct definition

How can I have a pointer to the next struct in the definition of this struct:
typedef struct A {
int a;
int b;
A* next;
} A;
this is how I first wrote it but it does not work.
You can define the typedef and forward declare the struct first in one statement, and then define the struct in a subsequent definition.
typedef struct A A;
struct A
{
int a;
int b;
A* next;
};
Edit: As others have mentioned, without the forward declaration the struct name is still valid inside the struct definition (i.e. you can used struct A), but the typedef is not available until after the typedef definition is complete (so using just A wouldn't be valid). This may not matter too much with just one pointer member, but if you have a complex data structure with lots of self-type pointers, may be less wieldy.
In addition to the first answer, without a typedef and forward declaration, this should be fine too.
struct A
{
int a;
int b;
struct A *next;
};
You are missing the struct before the A*
typedef struct A {
int a;
int b;
struct A* next;
} A;
You can go without forward declaration:
struct A {
int a;
int b;
struct A *next;
};
Please, you're in C, not C++.
If you really must typedef a struct (and most programmers that I work with would not¹), do this:
typedef struct _A {
int a;
int b;
struct _A *next;
} A;
to clearly differentiate between _A (in the struct namespace) and A (in the type namespace).
¹typedef hides the size and storage of the type it points to ― the argument (and I agree) is that in a low-level language like C, trying to hide anything is harmful and counterproductive. Get used to typing struct A whenever you mean struct A.
typedef struct {
values
} NAME;
This is shorter way to typedef a struct i think its the easiest notation, just don't put the name infront but behind.
you can then call it like
NAME n;
NAME *n; // if you'd like a ptr to it.
Anything wrong with this approach?

Resources