I write a struct
struct Tree{
struct Node *root;
struct Node NIL_t;
struct Node * const NIL; //sentinel
}
I want
struct Node * const NIL = &NIL_t;
I can't initialize it inside the struct.
I'm using msvs.
I use C, NOT C++.
I know I can use initialization list in C++.
How to do so in C?
If you are using C99, you can used designated initializers to do this:
struct Tree t = { .root = NULL, .NIL = &t.NIL_t };
This only works in C99, though. I've tested this on gcc and it seems to work just fine.
For those seeking a simple example, here it goes:
#include <stdio.h>
typedef struct {
const int a;
const int b;
} my_t;
int main() {
my_t s = { .a = 10, .b = 20 };
printf("{ a: %d, b: %d }", s.a, s.b);
}
Produces the following output:
{ a: 10, b: 20 }
A structure defines a data template but has no data itself. Since it has no data, there's no way to initialize it.
On the other hand, if you want to declare an instance, you can initialize that.
struct Tree t = { NULL, NULL, NULL };
Maybe something like this will suffice?
struct {
struct Node * const NIL;
struct Node *root;
struct Node NIL_t;
} Tree = {&Tree.NIL_t};
Related
I don't use the C language since years and now I need it again.
I'm trying to build a Red-Black Tree but I'm stuck at the beginning because I'm missing something about "structs".
Take a look to my "structs" declarations please, they are easy.
This is a header file included in Red_black_tree.c
#define BLACK 0 //defalut color
#define RED 1 //
struct Node { //create a black node by default, to have a red one look at "create_red_node"
struct Node *left = NULL;
struct Node *right= NULL;
int key = 0;
int value = 0;
char color = BLACK;
};
struct Root_t {
struct Node* Root;
};
struct Node* create_node () {
struct Node* black = (Node*) malloc (sizeof(Node));
return black;
}
struct Node* create_red_node () {
struct Node* red = create_node ();
red->color=RED;
return red;
}
Root_t* create_tree () {
struct Root_t* fake=(Root_t*) malloc (sizeof(Root_t));
struct fake->Root->left=create_red_node ();
struct fake->Root->right=create_red_node ();
return fake;
}
I compiled with "gcc Red_black_tree.c -o RBTree".
GCC says something like : "expected ';' at end of declaration list" 7 times, or "must use 'struct' tag to refer to type... ", "expected identifier...".
What do you think, is it good to create RBTree?
In C, you can not assign while you define the members of a struct
Instead of
struct T {
int a = 1;
int b = 2;
};
you need something like
struct T {
int a;
int b;
};
...
struct T t = {.a = 1, .b = 2};
In addition, all your members are set to 0 (NULL is an alias of (void *)0), when you want to allocate memory and initialize all to zero at the same time you can use calloc
struct Node* black = calloc(1, sizeof(*black)); // Dont cast malloc and friends
And here:
struct fake->Root->left=create_red_node();
, you don't want the struct keyword, instead:
fake->Root->left=create_red_node();
Another suggestion: do not hardcode the data of the red-black-tree in the structure, (int key, value;) even if it works you end up with a non reusable container, instead, use a generic pointer to void (void *data;) and a callback to your comparison functions in the implementation.
struct Node *insert(struct Node *root, int (*comparer)(const void *, const void *)) ...
maybe this is a duplicate but I can't find a proper solution for this problem... and I'm sort of being new to C development, and my problem is that I don't know how to initialized a nested struct, take a look for more info...
So the thing is the following:
// another_struct.h
struct AnotherStruct {
void (*some_function)();
}
extern struct AnotherStruct AnotherStruct;
// yet_another_struct.h
struct YetAnotherStruct {
void (*some_function)();
}
extern struct YetAnotherStruct YetAnotherStruct;
// my_struct.h
struct MyStruct1 {
struct AnotherStruct another;
struct YetAnotherStruct and_yet;
}
extern struct MyStruct1 MyStruct1;
In their respective .C file:
struct AnotherStruct AnotherStruct = {
.some_function = blabla
};
struct YetAnotherStruct YetAnotherStruct = {
.some_function = blablabla
};
// I want the initialization of MyStruct1 to have the struct pointing to the structs
struct MyStruct1 MyStruct1 = { /* ?? */ };
/* I was thinking something like this */
struct MyStruct1 MyStruct1 = {
.another = AnotherStruct,
.and_yet = YetAnotherStruct
};
But the compiler complains xD
So my ultimate goal is to be able access the child structures as:
MyStruct1.another.some_function();
Thanks a lot and sorry if this question is duplicate or is way to noob :)
Why don't you construct them like this (No pointer usage):
/* I was thinking something like this */
struct MyStruct1 MyStruct1 = {
.another = { //.another is your struct, just do construct like normal
.some_function = blabla
},
.and_yet = { //The same here.
.some_function = blablabla
}
};
Usage in your code is:
//Call function
MyStruct1.another.some_function();
Using pointers:
// my_struct.h, add pointers
struct MyStruct1 {
struct AnotherStruct *another; //Added pointers
struct YetAnotherStruct *and_yet; //Here too
}
and then use in your .c
struct AnotherStruct AnotherStruct = {
.some_function = blabla
};
struct YetAnotherStruct YetAnotherStruct = {
.some_function = blablabla
};
/* I was thinking something like this */
struct MyStruct1 MyStruct1 = {
.another = &AnotherStruct, //Added & for address
.and_yet = &YetAnotherStruct //Added & for address
};
And later access to your values like:
//Call your function now
MyStruct1.another->some_function();
#tilz0R not enough rep to comment. A little modification to your answer.
typedef struct {
int a_val;
} A;
typedef struct {
float b_val;
} B;
typedef struct {
A *a;
B *b;
} C;
C c = {
.a = &(A){ .a_val = 1 },
.b = &(B){ .b_val = 1. },
};
As for union thingie, probably it is about Microsoft extension syntax
typedef struct {
A;
B;
} C;
C c;
c.a_val = 1; // valid
Unfortunately this one is a non standard extension, moreover it is doomed to never become one since this was a committee decision to maintain compatibility with C++.
Per #Lundin comment. The following code is indeed possible in modern C:
typedef struct {
struct {
int a_val;
};
struct {
float b_val;
};
} C;
C c;
c.a_val = 1;
However this brings little to no benefit (apart from organizing your code) in case of embedding structures into structures. It is pretty cool than it comes to unions though:
typedef struct {
enum {
TA,
TB
} _;
union {
struct {
int a;
};
struct {
float b;
};
};
} C;
C c = { ._ = TA, .a = 1 };
Used compile line:
gcc -std=c11 -Wall -Wextra -pedantic
In the marked line I get an error Error - expected expression
#include <stdlib.h>
struct list_head {
struct list_head *next, *prev;
};
struct program_struct {
const char *name;
struct list_head node;
};
typedef struct program_struct program_t;
struct task_t {
program_t blocked_list;
};
int main() {
struct task_t *p = malloc(sizeof(*p));
p->blocked_list.name = NULL;
p->blocked_list.node = {&(p->blocked_list.node), &(p->blocked_list.node)}; //error
return 0;
}
I know I can replace this line with
p->blocked_list.node.next = &(p->blocked_list.node);
p->blocked_list.node.prev = &(p->blocked_list.node);
But can I make it work using {} like I tried in the first piece of code?
Initialization is allowed only when you define a variable. So, you can't use initializers in assignment.
You can instead use C99's compound literals:
p->blocked_list.node = (struct list_head) {&(p->blocked_list.node), &(p->blocked_list.node)}; //error
I have a family of large recursive functions that operate on trees. These trees are defined using "polymorphism", like so
struct foo {
enum abctype type;
union {
struct a ay;
struct b bee;
struct c cee;
}
};
where struct a... c are all nodes in the tree. Each node in the tree (i.e., any object of type struct a... c), points to an object of struct foo. For example:
struct a {
/* definitions */
/*...*/
struct foo *next;
};
Because of this, the struct dereferences end up getting very nested even though my functions aren't overreaching their purposes.
In this case, the nested dereferences are inevitable. It would be absurd to write cute little wrapper functions just to get rid of a ->. But, I've heard many programmers say that you shouldn't go past 3-4 dereferences or your "algorithm needs fixing".
So, what's the verdict? Does my code need fixing? are nested dereferences inefficient?
Edit:
Here's what my data structure looks like in more depth (they're not trees, as I have been told, unless linked list == tree):
struct a {
/* definitions */
/*...*/
struct foo *longitudinal;
};
struct b {
/* definitions */
/*...*/
struct foo *longitudinal;
struct b *transverse;
};
struct c {
/* definitions */
/*...*/
struct foo *longitudinal;
struct c *transverse;
};
Basically, the data structures are this way because the data they handle is organized this way (in my head). I just don't see a way to convert this to a binary tree.
A single pointer does not make a tree; it makes a list. Trees require at least two pointers. (You can find exceptions described at Wikipedia, but it is unlikely — though not impossible — that you're intending to use such an organization for your tree structure.)
I think your data organization is … well, if it is not wrong, then it is at least sub-optimal. You should almost certainly be using a structure more like:
struct tree
{
struct tree *left;
struct tree *right;
enum abctype type;
union {
struct a aye;
struct b bee;
struct c cee;
};
};
Where each of the single-letter structure types contains only the relevant (variant) data and not any tree-related pointers:
struct a
{
/* definitions */
/* …no struct tree *next; or anything similar… */
};
The tree traversal is now nice and uniform. Compare what used to be necessary with what is now necessary. Given the old struct foo *tp, your original code (probably) needed to do ghastly stuff like:
if (tp->type == TYPE_A)
process_next(tp->ay.next);
else if (tp->type == TYPE_B)
process_next(tp->bee.next);
else if (tp->type == TYPE_C)
process_next(tp->cee.next);
else
…report error…
(and similarly with a prev or left and right pointers, or whatever else you used to create an actual tree structure — though even as a list, this is more than a trifle messy).
With the revised scheme, given a struct tree *tp;, you now just use:
process_tree(tp->left);
process_data(tp);
process_tree(tp->right);
The data handling has to deal with the enumeration and accessing the appropriate portion of the anonymous union. This is much the same as before (except you don't need to futz with the tree structure pointers).
Working code
I observe that since you've not shown data for the structures a, b, and c, I've had to guess at what might be appropriate. If that sort of detail matters to you, it is important that you put that information in the question before people get to answer it. (That means, in part, don't go adding data fields to the structures now — you've already blown the opportunity to specify what is in them.)
This code works, more or less. The memory management doesn't have memory access errors, at least with the test data. The data isn't freed; that's an exercise for you to play with. Not all the error checking that should be there is there; that's another exercise for you. And the testing isn't all that comprehensive — guess what that means?
There could be some confusion about how your data structure is supposed to work. I've interpreted it as:
You can have a (longitudinal) list of items in arbitrary order, of type A, B or C. These are stored via struct foo, complete with the anonymous union.
Items of type B can have a transverse list of more type B items.
Items of type C can have a transverse list of more type C items.
Here's some code that works:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct a
{
char name[20];
};
struct b
{
double x;
double y;
struct b *transverse;
};
struct c
{
int height;
int width;
int depth;
struct c *transverse;
};
enum abctype { TYPE_A, TYPE_B, TYPE_C };
struct foo
{
struct foo *longitudinal;
enum abctype type;
union
{
struct a aye;
struct b bee;
struct c cee;
};
};
static struct foo *add_a_long(struct foo *head, const char *name)
{
struct foo *new_foo = malloc(sizeof(*new_foo));
if (new_foo != 0)
{
strncpy(new_foo->aye.name, name, sizeof(new_foo->aye.name)-1);
new_foo->aye.name[sizeof(new_foo->aye.name)-1] = '\0';
new_foo->type = TYPE_A;
new_foo->longitudinal = head;
}
return new_foo;
}
static struct foo *add_b_long(struct foo *head, double x, double y)
{
struct foo *new_foo = malloc(sizeof(*new_foo));
if (new_foo != 0)
{
new_foo->bee.x = x;
new_foo->bee.y = y;
new_foo->bee.transverse = 0;
new_foo->type = TYPE_B;
new_foo->longitudinal = head;
}
return new_foo;
}
static struct foo *add_c_long(struct foo *head, int height, int width, int depth)
{
struct foo *new_foo = malloc(sizeof(*new_foo));
if (new_foo != 0)
{
new_foo->cee.height = height;
new_foo->cee.width = width;
new_foo->cee.depth = depth;
new_foo->cee.transverse = 0;
new_foo->type = TYPE_C;
new_foo->longitudinal = head;
}
return new_foo;
}
static void add_b_trans(struct b *b, double x, double y)
{
struct b *new_b = malloc(sizeof(*new_b));
if (new_b != 0)
{
new_b->x = x;
new_b->y = y;
new_b->transverse = 0;
while (b->transverse != 0)
b = b->transverse;
b->transverse = new_b;
}
}
static void add_c_trans(struct c *c, int height, int width, int depth)
{
struct c *new_c = malloc(sizeof(*new_c));
if (new_c != 0)
{
new_c->height = height;
new_c->width = width;
new_c->depth = depth;
new_c->transverse = 0;
while (c->transverse != 0)
c = c->transverse;
c->transverse = new_c;
}
}
static void print_foo(const char *tag, const struct foo *head)
{
printf("\n%s:\n", tag);
while (head != 0)
{
switch (head->type)
{
case TYPE_A:
printf("A: %s\n", head->aye.name);
break;
case TYPE_B:
{
const struct b *bp = &head->bee;
printf("B-main: (%f,%f)\n", bp->x, bp->y);
while ((bp = bp->transverse) != 0)
printf("B-trans: (%f,%f)\n", bp->x, bp->y);
}
break;
case TYPE_C:
{
const struct c *cp = &head->cee;
printf("C-main: (%d,%d,%d)\n", cp->height, cp->width, cp->depth);
while ((cp = cp->transverse) != 0)
printf("C-trans: (%d,%d,%d)\n", cp->height, cp->width, cp->depth);
}
break;
}
head = head->longitudinal;
}
}
int main(void)
{
struct foo *head = 0;
head = add_a_long(head, "Caterpillar");
print_foo("1 item", head);
head = add_a_long(head, "Ununtrium");
print_foo("2 items", head);
head = add_b_long(head, 1.00000, 1.00000);
head = add_b_long(head, 3.14159, 2.78128);
print_foo("4 items", head);
assert(head->type == TYPE_B);
add_b_trans(&head->bee, 1.2345, 2.3456);
add_b_trans(&head->bee, 9.8765, 6.5432);
print_foo("4 items, 2 transverse B", head);
head = add_a_long(head, "Ununpentium");
head = add_c_long(head, 3, 4, 5);
head = add_c_long(head, 5, 12, 13);
print_foo("6 items", head);
assert(head->type == TYPE_C);
add_c_trans(&head->cee, 7, 20, 27);
add_c_trans(&head->cee, 9, 35, 36);
head = add_a_long(head, "Ununseptium");
head = add_a_long(head, "Ununoctium");
print_foo("Final", head);
return 0;
}
And this is the sample output I get:
1 item:
A: Caterpillar
2 items:
A: Ununtrium
A: Caterpillar
4 items:
B-main: (3.141590,2.781280)
B-main: (1.000000,1.000000)
A: Ununtrium
A: Caterpillar
4 items, 2 transverse B:
B-main: (3.141590,2.781280)
B-trans: (1.234500,2.345600)
B-trans: (9.876500,6.543200)
B-main: (1.000000,1.000000)
A: Ununtrium
A: Caterpillar
6 items:
C-main: (5,12,13)
C-main: (3,4,5)
A: Ununpentium
B-main: (3.141590,2.781280)
B-trans: (1.234500,2.345600)
B-trans: (9.876500,6.543200)
B-main: (1.000000,1.000000)
A: Ununtrium
A: Caterpillar
Final:
A: Ununoctium
A: Ununseptium
C-main: (5,12,13)
C-trans: (7,20,27)
C-trans: (9,35,36)
C-main: (3,4,5)
A: Ununpentium
B-main: (3.141590,2.781280)
B-trans: (1.234500,2.345600)
B-trans: (9.876500,6.543200)
B-main: (1.000000,1.000000)
A: Ununtrium
A: Caterpillar
The canonical way to go about this is to really use the structs like derived classes. I. e.:
struct base {
enum abctype type;
};
struct a {
struct base super;
//whatever other data members `a` happens to have
};
With this approach, you write functions taking a struct base*, which is subsequently cast to one of the subclasses once. Further manipulation of the object uses the derived class pointer with only a single ->.
Btw: If you include a function pointer within struct base, you can directly call the derived class's function (no switch required). Bonus points for grouping the function pointers in a struct of their own (instanciated as global tables), with a single pointer in struct base pointing to the correct function table. That would very, very close to what C++ does under the hood...
struct base_vtable {
void (*foo)(int, double);
int (*bar)(struct base*);
int (*baz)();
};
struct a_vtable {
struct base_vtable super;
double (*bim)();
dobule (*bam)();
};
struct base {
struct base_vtable vtable;
};
struct a {
struct base super;
//whatever
};
And then, somewhere in a .c file:
static struct a_vtable g_a_vtable = {
.super.foo = &a_foo,
.super.bar = &a_bar,
.super.baz = &a_baz,
.bim = a_bim,
.bam = a_bam
};
struct a* a_create(...) {
struct a* me = malloc(sizeof(*me));
me->super->vtable = g_a_vtable;
//further initialization
};
Is it possible to set default values for some struct member?
I tried the following but, it'd cause syntax error:
typedef struct
{
int flag = 3;
} MyStruct;
Errors:
$ gcc -o testIt test.c
test.c:7: error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘=’ token
test.c: In function ‘main’:
test.c:17: error: ‘struct <anonymous>’ has no member named ‘flag’
Structure is a data type. You don't give values to a data type. You give values to instances/objects of data types.
So no this is not possible in C.
Instead you can write a function which does the initialization for structure instance.
Alternatively, You could do:
struct MyStruct_s
{
int id;
} MyStruct_default = {3};
typedef struct MyStruct_s MyStruct;
And then always initialize your new instances as:
MyStruct mInstance = MyStruct_default;
you can not do it in this way
Use the following instead
typedef struct
{
int id;
char* name;
}employee;
employee emp = {
.id = 0,
.name = "none"
};
You can use macro to define and initialize your instances. this will make easiier to you each time you want to define new instance and initialize it.
typedef struct
{
int id;
char* name;
}employee;
#define INIT_EMPLOYEE(X) employee X = {.id = 0, .name ="none"}
and in your code when you need to define new instance with employee type, you just call this macro like:
INIT_EMPLOYEE(emp);
I agree with Als that you can not initialize at time of defining the structure in C.
But you can initialize the structure at time of creating instance shown as below.
In C,
struct s {
int i;
int j;
};
struct s s_instance = { 10, 20 };
in C++ its possible to give direct value in definition of structure shown as below
struct s {
int i;
s(): i(10) {}
};
You can do:
struct employee_s {
int id;
char* name;
} employee_default = {0, "none"};
typedef struct employee_s employee;
And then you just have to remember to do the default initialization when you declare a new employee variable:
employee foo = employee_default;
Alternatively, you can just always build your employee struct via a factory function.
Create a default struct as the other answers have mentioned:
struct MyStruct
{
int flag;
}
MyStruct_default = {3};
However, the above code will not work in a header file - you will get error: multiple definition of 'MyStruct_default'. To solve this problem, use extern instead in the header file:
struct MyStruct
{
int flag;
};
extern const struct MyStruct MyStruct_default;
And in the c file:
const struct MyStruct MyStruct_default = {3};
Hope this helps anyone having trouble with the header file.
If you are using gcc you can give designated initializers in object creation.
typedef struct {
int id = 0;
char *name = "none";
} employee;
employee e = {
.id = 0;
.name = "none";
};
Or , simply use like array initialization.
employee e = {0 , "none"};
Even more so, to add on the existing answers, you may use a macro that hides a struct initializer:
#define DEFAULT_EMPLOYEE { 0, "none" }
Then in your code:
employee john = DEFAULT_EMPLOYEE;
You can implement an initialisation function:
employee init_employee() {
empolyee const e = {0,"none"};
return e;
}
You can use combination of C preprocessor functions with varargs, compound literals and designated initializers for maximum convenience:
typedef struct {
int id;
char* name;
} employee;
#define EMPLOYEE(...) ((employee) { .id = 0, .name = "none", ##__VA_ARGS__ })
employee john = EMPLOYEE(.name="John"); // no id initialization
employee jane = EMPLOYEE(.id=5); // no name initialization
You can use some function to initialize struct as follows,
typedef struct
{
int flag;
} MyStruct;
MyStruct GetMyStruct(int value)
{
MyStruct My = {0};
My.flag = value;
return My;
}
void main (void)
{
MyStruct temp;
temp = GetMyStruct(3);
printf("%d\n", temp.flag);
}
EDIT:
typedef struct
{
int flag;
} MyStruct;
MyStruct MyData[20];
MyStruct GetMyStruct(int value)
{
MyStruct My = {0};
My.flag = value;
return My;
}
void main (void)
{
int i;
for (i = 0; i < 20; i ++)
MyData[i] = GetMyStruct(3);
for (i = 0; i < 20; i ++)
printf("%d\n", MyData[i].flag);
}
If you only use this structure for once, i.e. create a global/static variable, you can remove typedef, and initialized this variable instantly:
struct {
int id;
char *name;
} employee = {
.id = 0,
.name = "none"
};
Then, you can use employee in your code after that.
Another approach, if the struct allows it, is to use a #define with the default values inside:
#define MYSTRUCT_INIT { 0, 0, true }
typedef struct
{
int id;
int flag;
bool foo;
} MyStruct;
Use:
MyStruct val = MYSTRUCT_INIT;
An initialization function to a struct is a good way to grant it default values:
Mystruct s;
Mystruct_init(&s);
Or even shorter:
Mystruct s = Mystruct_init(); // this time init returns a struct
Another approach to default values. Make an initialization function with the same type as the struct. This approach is very useful when splitting large code into separate files.
struct structType{
int flag;
};
struct structType InitializeMyStruct(){
struct structType structInitialized;
structInitialized.flag = 3;
return(structInitialized);
};
int main(){
struct structType MyStruct = InitializeMyStruct();
};
You can create a function for it:
typedef struct {
int id;
char name;
} employee;
void set_iv(employee *em);
int main(){
employee em0; set_iv(&em0);
}
void set_iv(employee *em){
(*em).id = 0;
(*em).name = "none";
}
I think the following way you can do it,
typedef struct
{
int flag : 3;
} MyStruct;