os-sim.h
typedef enum {
PROCESS_NEW = 0,
PROCESS_READY,
PROCESS_RUNNING,
PROCESS_WAITING,
PROCESS_TERMINATED
} process_state_t;
typedef struct _pcb_t {
const unsigned int pid;
const char *name;
const unsigned int static_priority;
process_state_t state; <<---Trying to access this
op_t *pc;
struct _pcb_t *next;
} pcb_t;
file1.c
static pcb_t **current;
extern void yield(unsigned int cpu_id)
{
/* FIX ME */
while (1)
{
pthread_mutex_lock(¤t_mutex);
current[cpu_id].state = PROCESS_WAITING; ///<-------ERROR HERE
pthread_mutex_unlock(¤t_mutex);
break;
}
schedule(cpu_id);
}
in main method():
current = malloc(sizeof(pcb_t*) * 10);
I have error in this line current[cpu_id].state = PROCESS_WAITING;
error: request for member ‘state’ in something not a structure or union
What does this error mean?
Is this not the right way to access current array which holds pcb_t?
If so, how do i access the current array? and state field?
You're likely looking for:
current[cpu_id]->state = PROCESS_WAITING;
The type of current is pcb_t **. So the type of current[cpu_id] is pcb_t *.
Related
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).
Assuming that the following structures exist...
typedef struct MyFirstStruct
{
uint8_t someContent;
}
typedef struct MySecondStruct
{
MyFirstStruct* firstStructs;
uint8_t firstStructCount;
}
... and a function gets the following Parameter.
const MySecondStruct* const secondStruct
Is it allowed to change any value?
I am sure that this is not correct:
secondStruct->firstStructCount++.
But neither the Compiler nor PC-Lint complains about secondStruct->firstStructs->someContent++.
Is it allowed to do Change someContent because firstStructs is not const or is the behavior undefined?
Thanks!
The values of the nested struct(s) firstStructs can change as long as the pointer does not change. The constness of the pointer prevents the pointer value from changing, but the constness of the struct only means that its values must not change (i.e. the value of the pointer and the count).
You can modify the struct(s) pointed to by firstStructs arbitrarily without changing the pointer. You can also clearly see from the struct definition that this is legal, because firstStructs is a pointer to struct MyFirstStruct, not a pointer to const struct MyFirstStruct.
Here is an example to understand the principle without the const-pointer to const elements:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int x;
} Simple;
typedef struct {
Simple* s;
int scount;
} Nested;
int main()
{
Nested x;
x.scount = 10;
x.s = malloc(sizeof(Simple) * x.scount);
const Nested n = x;
for (int i = 0; i < n.scount; ++i)
{
n.s[i].x = i;
printf("%d\n", n.s[i].x);
}
}
It is OK and it was easy to check yourself:
typedef struct
{
uint8_t someContent;
} MyFirstStruct;
typedef struct
{
MyFirstStruct* firstStructs;
uint8_t firstStructCount;
}MySecondStruct;
MyFirstStruct fs;
MySecondStruct str = {.firstStructs = &fs};
const MySecondStruct* const secondStruct = &str;
int main()
{
secondStruct->firstStructs->someContent++;
}
but did not as the posted code was full of syntax errors.
You cant of course change the pointer itself:
This will give you errors:
typedef struct
{
uint8_t someContent;
} MyFirstStruct;
typedef struct
{
MyFirstStruct* firstStructs;
uint8_t firstStructCount;
}MySecondStruct;
MyFirstStruct fs[2];
MyFirstStruct ss;
MySecondStruct str = {.firstStructs = fs};
const MySecondStruct* const secondStruct = &str;
int main()
{
secondStruct->firstStructs++->someContent++;
secondStruct->firstStructs = &ss;
}
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.
Hie guys. I am studying structures and pointers using the book called Pointers in C: A Hands on Approach and on page 107, I came across an incomplete example of struct type casting. I tried to make it work by just implementing the function receivedata() ,adding headers and making a few changes.
This is the complete code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct signature
{
char sign;
char version;
};
struct id
{
char id;
char platform;
};
struct data
{
struct id idv;
struct signature sig;
char data[100];
};
static void receivedata(struct data *d);
static struct signature *extractsignature(struct data *d);
static struct id *extractid(struct data *d);
int main(int argc, char *argv[])
{
/* Actual line in book is :
* struct data *img; with no memory allocation or assignment to NULL.
* Had errors so i allocated memory on the heap before passing the value to
* Receivedata(); */
struct data *img = malloc(sizeof(struct data));
receivedata(img);
/* Actual line in book is :
* struct id *idval = extractid(&img);
* struct signature *sig = extractsignature(&img);
* This is obviously erroneous because &img is a pointer
* to a pointer (struct data**) which is not the data type for
* the extract functions' argument */
struct id *idval = extractid(img);
struct signature *sig = extractsignature(img);
printf("For signature:\n");
printf("sign = %c", sig->sign);
printf(" version = %c\n\n", sig->version);
printf("For id:\n");
printf("id = %c", idval->id);
printf(" platform = %c", idval->platform);
printf("\ndata = %s", img->data);
return 0;
}
static struct signature *extractsignature(struct data *d)
{
struct signature *sig = (struct signature *)d;
return sig;
}
static struct id *extractid(struct data *d)
{
struct id *idv = (struct id *)d;
return idv;
}
static void receivedata(struct data *d)
{
struct data *dptr = d;
char *ch = "CODING IS COOL!";
dptr->sig.sign = 's';
dptr->sig.version = '1';
dptr->idv.id = 'i';
dptr->idv.platform = 'p';
strncpy(dptr->data, ch, strlen(ch));
return;
}
What I would like to understand is the casting inside the function extractid() and extraxtsignature() because it seems we are casting struct data * so as to retrieve its individual members. I ran the program and what i get is the value of the first member of struct data for both sig member and id members. Here is the output when struct id comes first in the struct data:
For signature:
sign = i version = p
For id:
id = i platform = p
data = CODING IS COOL!
and this when struct signature is the first element:
For signature:
sign = s version = 1
For id:
id = s platform = 1
data = CODING IS COOL!
and finally, this when char data[100] is the first element:
For signature:
sign = C version = O
For id:
id = C platform = O
data = CODING IS COOL!
May you please explain this type of casting, when to use it and the best practices. Thank you very much.
struct data
{
struct id idv;
struct signature sig;
char data[100];
};
For the above definition, the extractid function below is valid and will get right results.
static struct id *extractid(struct data *d)
{
struct id *idv = (struct id *)d;
return idv;
}
This is because, struct id is the first member of the struct data. So, when you have struct data *d, the d points to the starting address of struct data and which is same as the starting address of the first member struct id.
So, if you are casting for the first member of the struct, then it is right as per the code you have provided above.
This question already has answers here:
Object-orientation in C
(23 answers)
Closed 8 years ago.
Is it possible to model inheritance using C? How? Sample code will help.
Edit: I am looking to inherit both data and methods. Containership alone will not help. Substitutability - using any derived class object where a base class object works - is what I need.
It is very simple to go like this:
struct parent {
int foo;
char *bar;
};
struct child {
struct parent base;
int bar;
};
struct child derived;
derived.bar = 1;
derived.base.foo = 2;
But if you use MS extension (in GCC use -fms-extensions flag) you can use anonymous nested structs and it will look much better:
struct child {
struct parent; // anonymous nested struct
int bar;
};
struct child derived;
derived.bar = 1;
derived.foo = 2; // now it is flat
You can definitely write C in a (somewhat) object-oriented style.
Encapsulation can be done by keeping the definitions of your structures
in the .c file rather than in the associated header.
Then the outer world handles your objects by keeping pointers to them,
and you provide functions accepting such pointers as the "methods"
of your objects.
Polymorphism-like behavior can be obtained by using functions pointers,
usually grouped within "operations structures",
kind of like the "virtual method table" in your C++ objects
(or whatever it's called).
The ops structure can also include other things such as
constants whose value is specific to a given "subclass".
The "parent" structure can keep a reference to ops-specific data
through a generic void* pointer.
Of course the "subclass" could repeat the pattern for multiple levels
of inheritance.
So, in the example below, struct printer is akin to an abstract class,
which can be "derived" by filling out a pr_ops structure,
and providing a constructor function wrapping pr_create().
Each subtype will have its own structure which will be "anchored"
to the struct printer object through the data generic pointer.
This is demontrated by the fileprinter subtype.
One could imagine a GUI or socket-based printer,
that would be manipulated regardless by the rest of the code
as a struct printer * reference.
printer.h:
struct pr_ops {
void (*printline)(void *data, const char *line);
void (*cleanup)(void *data);
};
struct printer *pr_create(const char *name, const struct output_ops *ops, void *data);
void pr_printline(struct printer *pr, const char *line);
void pr_delete(struct printer *pr);
printer.c:
#include "printer.h"
...
struct printer {
char *name;
struct pr_ops *ops;
void *data;
}
/* constructor */
struct printer *pr_create(const char *name, const struct output_ops *ops, void *data)
{
struct printer *p = malloc(sizeof *p);
p->name = strdup(name);
p->ops = ops;
p->data = data;
}
void pr_printline(struct printer *p, const char *line)
{
char *l = malloc(strlen(line) + strlen(p->name) + 3;
sprintf(l, "%s: %s", p->name, line);
p->ops->printline(p->data, l);
}
void pr_delete(struct printer *p)
{
p->ops->cleanup(p->data);
free(p);
}
Finally, fileprinter.c:
struct fileprinter {
FILE *f;
int doflush;
};
static void filepr_printline(void *data, const char *line)
{
struct fileprinter *fp = data;
fprintf(fp->f, "%s\n", line);
if(fp->doflush) fflush(fp->f);
}
struct printer *filepr_create(const char *name, FILE *f, int doflush)
{
static const struct ops = {
filepr_printline,
free,
};
struct *fp = malloc(sizeof *fp);
fp->f = f;
fp->doflush = doflush;
return pr_create(name, &ops, fp);
}
Yes, you can emulate heritance en C using the "type punning" technique. That is the declaration of the base class (struct) inside the derived class, and cast the derived as a base:
struct base_class {
int x;
};
struct derived_class {
struct base_class base;
int y;
}
struct derived_class2 {
struct base_class base;
int z;
}
void test() {
struct derived_class d;
struct derived_class2 d2;
d.base.x = 10;
d.y = 20;
printf("x=%i, y=%i\n", d.base.x, d.y);
}
But you must to declare the base class in the first position in you derived structure, if you want to cast the derived as base in a program:
struct base *b1, *b2;
b1 = (struct base *)d;
b2 = (struct base *)d2;
b1->x=10;
b2->x=20;
printf("b1 x=%i, b2 x=%i\n", b1->x, b2->x);
In this snippet you can use the base class only.
I use this technique in my projects: oop4c
It should be possible, at least to some extent.
What exactly do you need to model? The inheritance of the data or the methods?
Edit: Here's a short article that I found: http://fluff.info/blog/arch/00000162.htm
I've used an object system in C that used late-bound methods, which allowed for object-orientation with reflection.
You can read about it here.
#include <stdio.h>
///////Class Cobj
typedef struct Cobj{
int x;
void (*setptr)(char * s,int val);
int (*getptr)(char * s);
} Cobj;
void set(char * s,int val)
{
Cobj * y=(Cobj *)s;
y->x=val;
}
int get(char * s){
Cobj * y=(Cobj *)s;
return y->x;
}
///////Class Cobj
Cobj s={12,set,get};
Cobj x;
void main(void){
x=s;
x.setptr((char*)&x,5);
s.setptr((char*)&s,8);
printf("%d %d %d",x.getptr((char*)&x),s.getptr((char*)&s) ,sizeof(Cobj));
}
This link might be useful -> link
Basic example will be like follow
struct BaseStruct
{
// some variable
}
struct DerivedStruct
{
struct BaseStruct lw;
// some more variable
};