The below is my code. Compiler generates the errors as
#include<stdio.h>
struct Shelf{
int clothes;
int *books;
};
struct Shelf b;
b.clothes=5;
*(b.books)=6;
Compiler generates the errors as below for both statements b.clothes=5; and b->books=6; in above code.
error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘->’ token
I'm not a beginner at C and I believe that what I have written is correct. Kindly solve my problem
FIRST
You cannot do this
struct Shelf{
int clothes;
int books;
};
struct Shelf b;
b.clothes=5;
b.books=6;
In global scope
You can assign value inside a function
int main (void )
{
b.clothes=5;
b.books=6;
}
Or initializing values on declaration
struct Shelf b = { .clothes = 5, .books = 6 };
Moreover as you can see b is not a pointer so using -> is not correct: use . to access members of struct.
SECOND
Your struct has a pointer member book
struct Shelf{
int clothes;
int *books;
};
What you can do is to set it to the address of another variable, like
int book = 6;
struct Shelf b = { .clothes = 5, .books = &book };
Or allocate memory for that pointer like
int main (void )
{
b.clothes=5;
b.books=malloc(sizeof(int));
if (b.books != NULL)
{
*(b.books) = 6;
}
}
BTW I guess you want an array of books, so
int main (void )
{
b.clothes=5;
b.books=malloc(sizeof(int) * MAX_N_OF_BOOKS);
if (b.books != NULL)
{
for (int i=0; i<MAX_N_OF_BOOKS; i++)
b.books[i] = 6;
}
}
COMPETE TEST CODE
#include <stdio.h>
#include <stdlib.h>
struct Shelf
{
int clothes;
int *books;
};
int main(void)
{
struct Shelf b;
b.clothes = 5;
b.books = malloc(sizeof(int));
if (b.books != NULL)
{
*(b.books) = 6;
}
printf ("clothes: %d\n", b.clothes);
printf ("book: %d\n", *(b.books) );
}
OUTPUT
clothes: 5
book: 6
b is a struct, not a pointer, so -> is not correct.
It's like doing (*b).books, which is wrong.
struct Shelf{
int clothes;
int *books;
};
One data member of the struct is a pointer, however:
struct Shelf b;
is not a pointer, it is just a struct as I said before.
As for your question in comment:
b.clothes=5;
is correct. Also something like this would be ok:
int number = 6;
b.books = &number;
-> operator used to access of member of struct via pointer. b is not dynamically allocated so b->books=6; is wrong. You should first allocate memory for member books and then dereference it.
b.books = malloc(sizeof(int));
*(b.books)= 6;
Related
warning: returning 'struct example_str **' from a function with incompatible return type 'struct example_str *' [-Wincompatible-pointer-types]
return &(example1_str->member2[index]);
Please help understand why the warning is being generated. When example1_struct->member[index] is called, my understanding is it should return (struct example_struct*) Please help me understand the reason for warning. Thank you in advance.
#include <stdio.h>
#include "stdbool.h"
struct example_str{
int member1;
struct example_str* member2[5];
};
struct example_str* Reftest(int index);
void function2(int id, int* SigVal);
struct example_str* example1_str;
int main()
{
_Bool test;
int Val = (int) test;
function2(10,&Val);
return 0;
}
void function2(int id, int* SigVal){
struct example_str* ptr_to_str;
ptr_to_str = Reftest(1);
ptr_to_str -> member2[1] -> member1 = id;
printf("%d",ptr_to_str -> member2[1] -> member1);
}
struct example_str* Reftest(int index){
return &(example1_str->member2[index]);
}
struct example_str
{
int member1;
struct example_str* member2[5];
};
example_str has 2 members and
member1 is int
member2 is struct example_str*[5], a.k.a. an array of 5 pointers to struct example_str, from member2[0] to member2[4]. 5 pointers.
refTest returns struct example_str*, the same type of each member2
You can align the declarations to see better
struct example_str
{
int member1;
struct example_str* member2[5];
};
struct example_str* Reftest(int index);
So it is clear that whathever member2 is, it is the same that Reftest() returns.
So if you declare, as you did
struct example_str* Reftest(int index)
{
return &(example1_str->member2[index]);
}
As & is the operator address of, you are returning the address of member2[], that is itself a pointer --- struct example_str* --- and for sure its type is struct example_str**
The compilers says that
so0729.c:35:12: warning: returning 'struct example_str **' from a function
with incompatible return type
struct example_str *' [-Wincompatible-pointer-types]
35 | return &(example1_str->member2[index]);
| ^~~~~~~~~~~~~~
And it is what it is. Just take the & off.
Consider using typedef. It is usual and can lead to a code easier to read. And avoid global things declared outside main()
Example
This is a variation of your code using the pointers to pass references back and forth to the structs
#include <stdio.h>
typedef struct st_example_str
{
int member1;
struct st_example_str* member2[5];
} Example;
Example* Reftest(Example*, unsigned);
void function2(Example*, unsigned, int* SigVal);
int main()
{
Example A = {.member1 = 10};
Example B = {.member1 = 11};
Example C = {.member1 = 12};
Example D = {.member1 = 13};
Example E = {.member1 = 14};
Example ex1;
ex1.member1 = 1;
ex1.member2[0] = &A;
ex1.member2[1] = &B;
ex1.member2[2] = &C;
ex1.member2[3] = &D;
ex1.member2[4] = &E; // not used
C.member2[0] = &ex1; // cycle
D.member2[0] = &ex1; // cycle
E.member2[0] = &ex1; // cycle
char test = 42;
int Val = (int)test;
function2(&ex1, 2, &Val); // should set member1 of C to 42...
printf("ids (member1) pointed from the array inside ex1: ");
for (int i = 0; i < 5; i += 1)
printf("%d ", ex1.member2[i]->member1);
printf("\n");
printf("member1 for ex1: %d\n", ex1.member1);
return 0;
}
void function2(Example* E, unsigned id, int* SigVal)
{
// sets member1 of struct pointed by E->member[id] to
// the value pointed to by SigVal
Example* ptr_to_str = Reftest(E, id);
ptr_to_str->member2[0]->member1 = *SigVal;
}
Example* Reftest(Example* E, unsigned index)
{
return E->member2[index];
}
Example output
ids (member1) pointed from the array inside ex1: 10 11 12 13 14
member1 for ex1: 42
And you see that 42, the value of test, gets set in ex1 using a few references
I've one solid structure and another structure with pointers. The purpose of program is to assign: solid structure to structure with pointers and access each solid structure member using other structure pointer.
I've problem statement: as two structure member as not symmetric, when i assign solid structure address to structure with pointers, member pointer initialization go bad and crash the system.
Does anyone have any approach to find a solution for this problem in an optimized way?
----------------------------------------------------------------------- program -----------------------------
#include <stdio.h>
#include <string.h>
#include <stddef.h>
/* ===================== Binding Structure ================================= */
typedef struct
{
char id;
}tmodel;
typedef struct
{
char id;
}tbrand;
typedef struct
{
char id;
}tcommercialRef;
typedef struct
{
char id;
}tserialnum;
typedef struct
{
tmodel *smodel;
tbrand *sbrand;
tcommercialRef *scommref;
tserialnum *sslnum;
}tmetadata;
typedef struct
{
tmetadata *smetadata;
}tlink;
typedef struct
{
tlink *slink;
}trefernce;
typedef struct
{
char id[10];
int ttl;
int tss;
trefernce *sref;
}telectrical;
/* ===================== Application Strucuture ==============================*/
void filldata(telectrical *elec);
typedef struct
{
tmodel smodel;
tbrand sbrand;
tcommercialRef scommref;
tserialnum sslnum;
}Ymetadata;
typedef struct
{
Ymetadata smetadata;
}slink;
typedef struct
{
slink glink;
}refernce;
typedef struct
{
char id[10];
int ttl;
int tss;
refernce grefernce;
}gtelectrical;
//solid strucutre object
gtelectrical obj;
//structure pointer object
telectrical *elec = {0};
/* =============================== main.c =================================== */
int main()
{
printf("test");
//static void **p = (void *)&elec;
obj.tss = 55;
obj.ttl = 100;
obj.grefernce.glink.smetadata.smodel.id = 5;
obj.grefernce.glink.smetadata.sbrand.id = 6;
obj.grefernce.glink.smetadata.scommref.id = 7;
obj.grefernce.glink.smetadata.sslnum.id = 8;
elec = (telectrical *)&obj;
//elec structure -> sref pointer goes bad as it's not same type as "grefernce"
//*p = (void *)&obj;
//static long x = (long) offsetof( telectrical, sref);
//(long) offsetof(struct telectrical, sref);
//*(*p + x) = obj.grefernce.glink.smetadata.;
elec->id[0] = 0;
elec->id[1] = 1;
elec->id[2] = 2;
elec->ttl = 5;
elec->tss = 10;
elec->sref->slink->smetadata->sslnum->id = 4;
elec->sref->slink->smetadata->sbrand->id = 1;
elec->sref->slink->smetadata->scommref->id = 2;
elec->sref->slink->smetadata->smodel->id = 3;
//filldata(elec);
printf("------");
printf("%d\n",elec->sref->slink->smetadata->sslnum->id);
printf("%d\n",elec->sref->slink->smetadata->sbrand->id);
printf("%d\n",elec->sref->slink->smetadata->scommref->id);
printf("%d\n",elec->sref->slink->smetadata->smodel->id);
return 0;
}
/* //////////////////////////////////////// user scope ////////////////////////////// */
void filldata(telectrical *pelec)
{
pelec->id[0] = 0;
pelec->id[1] = 1;
pelec->id[2] = 2;
pelec->ttl = 5;
pelec->tss = 10;
//pelec->sref->slink->smetadata->sslnum->id = 4;
//pelec->sref->slink->smetadata->sbrand->id = 1;
//pelec->sref->slink->smetadata->scommref->id = 2;
//pelec->sref->slink->smetadata->smodel->id = 3;
}
You are not assigning memory for the pointers to other struct present inside another struct. Here is something which might help you in multi-level memory allocation and assignment:
#include<stdio.h>
#include<stdlib.h>
typedef struct A
{
int i;
}A_Node;
typedef struct B
{
A_Node *A_ptr;
}B_Node;
typedef struct C
{
B_Node *B_ptr;
}C_Node;
int main(void)
{
//ACCESSING-MANIPULATING A USING B
B_Node B_obj;
B_obj.A_ptr=malloc(sizeof(*(B_obj.A_ptr)));
(B_obj.A_ptr)->i=192;
A_Node A_obj=*(B_obj.A_ptr); //For checking if the allocation is successful and good
printf("%d\n",A_obj.i);
//ACCESSING-MANIPULATING A USING C
C_Node C_obj;
C_obj.B_ptr=malloc(sizeof(*(C_obj.B_ptr))); //allocating space for struct of B using C object
(C_obj.B_ptr)->A_ptr = malloc(sizeof(*((C_obj.B_ptr)->A_ptr))); //allocating space for struct of A using B Struct for which space was allocated in previous step by C struct
((C_obj.B_ptr)->A_ptr)->i=876;
A_obj=*((C_obj.B_ptr)->A_ptr); //For checking if the allocation is successful and good
printf("%d\n",A_obj.i);
return 0;
}
Read the code and ask if there are any doubts, in the similar way this multi-level struct-inside-struct can be created (though it would be ugly).
I'm having trouble with a piece of code where a typedef array is created of a struct. That typedef is then used in another struct.
When receiving the typedef in a function and initialising the struct with the typedef in it, I only get data of the first element in the array.
Below I have a simplified example of what I'm getting at the moment.
struct simple_struct {
double a;
};
typedef struct simple_struct arr_typedef[2];
struct struct_with_typedef {
const arr_typedef typedef_arr;
};
void foo(const arr_typedef arg_s) {
struct struct_with_typedef test = {
*arg_s
};
int i;
for (i = 0; i < 2; i++) {
printf("value: %f \n", test.typedef_arr[i].a);
}
}
int main(int argc, char* argv[]) {
arr_typedef d_test = { {1}, {2} };
foo(d_test);
return 1;
}
When compiled, using gcc 4.4, and run I see the following output:
~/public > ./test
value: 1.000000
value: 0.000000
Would someone be able to explain why the value of the second item isn't available?
If I leave out the dereference I get the following error whilst compiling, which I also don't get:
test.c:82: error: incompatible types when initializing type 'double' using type 'const struct simple_struct *'
I have removed the typedef and the same result persists. Sort of understand that indeed that one initialiser value is given. But there is only one member in the struct, or are they expanded in the background?
If so, how would you initialise both values?
struct simple_struct {
double a;
};
struct struct_with_arr {
const struct simple_struct struct_arr[2];
};
void foo(const struct simple_struct arg_s[2]) {
struct struct_with_arr test = {{*arg_s}};
int i;
for (i = 0; i < 2; i++) {
printf("value: %f \n", test.struct_arr[i].a);
}
}
int main(int argc, char* argv[]) {
struct simple_struct d_test[2] = { {1}, {2} };
foo(d_test);
return 1;
}
In this declaration
struct struct_with_typedef test = {
*arg_s
};
there is used an object of the type struct simple_struct to initialize an array of the type const arr_typedef.
Firstly you need to enclose the initializer in braces and add an initializer for the second element of the array if you want to do so.
A correct way to initialize the array is the following
#include <stdio.h>
struct simple_struct
{
double a;
};
typedef struct simple_struct arr_typedef[2];
struct struct_with_typedef
{
const arr_typedef typedef_arr;
};
void foo( const arr_typedef arg_s )
{
struct struct_with_typedef test =
{
{ arg_s[0], arg_s[1] }
};
for ( int i = 0; i < 2; i++ )
{
printf("value: %f \n", test.typedef_arr[i].a);
}
}
int main( void )
{
arr_typedef d_test = { {1}, {2} };
foo(d_test);
return 0;
}
The program output is
value: 1.000000
value: 2.000000
You can write the initializers also the following way
struct struct_with_typedef test =
{
{ *arg_s, *( arg_s + 1 ) }
};
Take into account that an array designator used as an initializer expression is implicitly converted to pointer to its first element. Dereferencing the pointer you get the first element itself.
There is no syntax in C for initializing an array with a single initializer representing another array to copy values from.
To fix your code you could do one of these options:
List the members: struct struct_with_arr test = {{arg_s[0], arg_s[1]}};
Change the function to accept struct struct_with_arr as the parameter type, in which case you can use struct struct_with_arr test = arg;
Copy without an initializer: struct struct_with_arr test; memcpy(&test.struct_arr, arg_s, sizeof test.struct_arr);. (Actually you can't use this option since you have defined the struct element as const ... not really a great idea in the first place in my opinion)
For completeness I will mention the code:
struct struct_with_arr foo = *(struct struct_with_arr *)arg_s;
This is one of those things that is technically undefined behaviour (if the argument source was not actually a struct_with_arr) but is likely to work on any actual compiler that exists. My advice would be to not do this.
The language is C.
Recently here I asked for and received help making the function qsort work for an array of structures.
I am now studying bit-fields and trying to make a program that uses a structure that uses another structure using bitfields and then sorting it out. But when I compile it, I get error at the compare function that "dereferencing pointer to incomplete type" and I had many trials again but still can't make it work. Can you folks help me?
Here's the code:
#include <stdio.h>
#include <stdlib.h>
int compare(const void * a, const void * b)
{
struct emp *orderA = (struct emp *)a;
struct emp *orderB = (struct emp *)b;
return (orderA->d.year - orderB->d.year);
}
int main()
{
int i;
struct date{
unsigned day : 5;
unsigned month : 4;
unsigned year : 12;
};
struct emp {
char name[10];
struct date d;
};
struct emp e[5];
for(i = 0; i < 5; i++)
{
scanf("%s %d %d %d", e[i].name, e[i].d.day, e[i].d.month, e[i].d.year);
}
qsort(e, 5, sizeof(struct emp), compare);
for(i = 0; i < 5; i++)
{
printf("%s %d %d %d\n", e[i].name, e[i].d.day, e[i].d.month, e[i].d.year);
}
return 0;
}
Why this doesn't work
Since you've defined struct emp inside your main function, it only exists inside your main function.
As such, when you attempt to cast to struct emp* in your compare function, the type does not exist.
If you want this code to work, you should move
struct emp {
char name[10];
struct date d;
};
out of your main function and above your compare function.
Ideally you should move it into its own header file and include that.
The same applies to your struct date since it is used inside struct emp. So move
struct date{
unsigned day : 5;
unsigned month : 4;
unsigned year : 12;
};
out of your main function as well.
Scopes in C
Keep in mind as a general rule in C that any non-static identifier declared or defined inside a scope (meaning between a set of {}) is local to that scope and cannot be accessed outside of that scope.
If I have a struct in C that has an integer and an array, how do I initialize the integer to 0 and the first element of the array to 0, if the struct is a member another struct so that for every instance of the other struct the integer and the array has those initialized values?
Initialisers can be nested for nested structs, e.g.
typedef struct {
int j;
} Foo;
typedef struct {
int i;
Foo f;
} Bar;
Bar b = { 0, { 0 } };
I hope this sample program helps....
#include <stdio.h>
typedef struct
{
int a;
int b[10];
}xx;
typedef struct
{
xx x1;
char b;
}yy;
int main()
{
yy zz = {{0, {1,2,3}}, 'A'};
printf("\n %d %d %d %c\n", zz.x1.a, zz.x1.b[0], zz.x1.b[1], zz.b);
return 0;
}
yy zz = {{0, {0}}, 'A'}; will initialize all the elements of array b[10] will be set to 0.
Like #unwind suggestion, In C all instances created should initialized manually. No constructor kind of mechanism here.
You can 0-initialize the whole struct with {0}.
For example:
typedef struct {
char myStr[5];
} Foo;
typedef struct {
Foo f;
} Bar;
Bar b = {0}; // this line initializes all members of b to 0, including all characters in myStr.
C doesn't have constructors, so unless you are using an initializer expression in every case, i.e. write something like
my_big_struct = { { 0, 0 } };
to initialize the inner structure, you're going to have to add a function and make sure it's called in all cases where the structure is "instantiated":
my_big_struct a;
init_inner_struct(&a.inner_struct);
Here is an alternative example how you would do things like this with object-oriented design. Please note that this example uses runtime initialization.
mystruct.h
#ifndef MYSTRUCT_H
#define MYSTRUCT_H
typedef struct mystruct_t mystruct_t; // "opaque" type
const mystruct_t* mystruct_construct (void);
void mystruct_print (const mystruct_t* my);
void mystruct_destruct (const mystruct_t* my);
#endif
mystruct.c
#include "mystruct.h"
#include <stdlib.h>
#include <stdio.h>
struct mystruct_t // implementation of opaque type
{
int x; // private variable
int y; // private variable
};
const mystruct_t* mystruct_construct (void)
{
mystruct_t* my = malloc(sizeof(mystruct_t));
if(my == NULL)
{
; // error handling needs to be implemented
}
my->x = 1;
my->y = 2;
return my;
}
void mystruct_print (const mystruct_t* my)
{
printf("%d %d\n", my->x, my->y);
}
void mystruct_destruct (const mystruct_t* my)
{
free( (void*)my );
}
main.c
int main (void)
{
const mystruct_t* x = mystruct_construct();
mystruct_print(x);
mystruct_destruct(x);
return 0;
}
You don't necessarily need to use malloc, you can use a private, statically allocated memory pool as well.