what exactly means this struct definition? - c

sorry for this newbie question but I don't find any good resource on web to explain what this means:
struct {
struct spinlock lock;
struct proc proc[NPROC]; //NPROC = 64
} ptable;
I see the resources over the web and find these types of define a struct:
//first method
struct Foo { ... };
//second method
typedef struct Foo { ... } Foo;

struct foo { ... };
The struct tag (foo here) is optional. If it's omitted like in your example, you can use the variable ptable which is of this type, but you can't define other variables of this type later.

struct
{
struct spinlock lock;
struct proc proc[NPROC]; //NPROC = 64
}
ptable;
This defines a nameless struct and at the same time declares a variable named ptable
As pointed by Yu Hao, you can't define variables of this struct type later. You can make as many variables at the time you define the nameless struct
struct
{
/* your variables*/
} a,b[2] ;
as opposed to a named struct,
struct my_struct
{
/* your variables*/
} a,b[2] ;
and you can define variables later as struct my_struct c

Related

Circular dependency in single C header file. Forward declaration needed?

#ifndef STAGE_TABLE_DEFINITION_HEADER
#define STAGE_TABLE_DEFINITION_HEADER
typedef stage_table_context_t* (*stage_table_function_t)(stage_table_context_t*);
typedef struct {
const char* stage_name;
stage_table_function_t* function;
} stage_t;
typedef struct {
uint32_t error_number;
stage_t* current_stage;
} stage_table_context_t;
#endif
Getting an unknown type error on stage_table_context_t.
The function pointer stage_table_function_t refers to stage_table_context_t and stage_table_context_t refers to stage_table_function_t.
Obviously positioning doesn't matter here since either orientation will result in an issue. Seems I need to forward declare the stage table context structure, but not sure how to do this with a typedef.
Apologies for the stupid question, I've been away from C for 6 months and I'm having a bit of a brain fart.
edit: Fixed some typo's in the code.
You can make the declaration of a struct before its definition:
/* declaration */
struct foo;
.....
/* definition */
struct foo
{
....
};
Anywhere you write struct foo is a declaration of the struct, so you don't have to put it in a separate line, you can have it in a typedef, pointer declaration, etc..
Just be aware that sometimes, like in variable declarations of type struct foo you also need the definition (to calculate the variable size);
/* declare struct foo ..*/
struct foo;
/* .. or declare struct foo ..*/
typedef struct foo foo;
/* .. or declare struct foo ..*/
struct foo *p;
/* .. or declare struct foo */
int bar (struct foo *p);
/* Not valid since we don't have definition yet */
struct foo f1;
/* definition */
struct foo
{
....
};
/* Valid */
struct foo f2;
In your case you haven't given the struct a name; you've just made a typedef that is an alias for an anonymous struct. So to forward declare your struct you have to give it a name:
/*
forward declare the `struct stage_table_context_t` and give it a typedef alias
with the same name as the structs name
*/
typedef struct stage_table_context_t stage_table_context_t;
typedef stage_table_context_t* (*stage_table_function_t)(stage_table_context_t*);
typedef struct {
const char* stage_name;
stage_table_function_t* function;
} stage_t;
struct stage_table_context_t{
uint32_t error_number;
stage_t* current_stage;
} stage_table_context_t;
You just have to tell the compiler that stage_table_context_t shall be a struct; by that, you implicitly forward-declare the struct stage_table_context_t, which's actual definition may then come later. Note that a typedef does not define a struct, it just introduces an alias. So the actual definition is struct stage_table_context_t { ..., regardless of whether you introduce an alias for it or not (and regardless of which name you use for the alias).
typedef struct stage_table_context_t* (*stage_table_function_t)(struct stage_table_context_t*);
typedef struct {
const char* stage_name;
stage_table_function_t* function;
} stage_t;
struct stage_table_context_t {
uint32_t error_number;
stage_t* current_stage;
};
// optional (if you want to use "stage_table_context_t" as an alias for "struct stage_table_context_t"):
typedef struct stage_table_context_t stage_table_context_t;

What's the difference between `typedef struct X { }` and `typedef struct { } X`?

What's the difference between these two declarations in C:
typedef struct square{
//Some fields
};
and
typedef struct{
//Some fields
} square;
The first declaration:
typedef struct square {
// Some fields
};
defines a type named struct square. The typedef keyword is redundant (thanks to HolyBlackCat for pointing that out). It's equivalent to:
struct square {
//Some fields
};
(The fact that you can use the typedef keyword in a declaration without defining a type name is a glitch in C's syntax.)
This first declaration probably should have been:
typedef struct square {
// Some fields
} square;
The second declaration:
typedef struct {
// Some fields
} square;
defines an anonymous struct type and then gives it the alias square.
Remember that typedef by itself doesn't define a new type, only a new name for an existing type. In this case the typedef and the (anonymous) struct definition happen to be combined into a single declaration.
struct X { /* ... */ };
That create a new Type. So you can declare this new type by
struct X myvar = {...}
or
struct X *myvar = malloc(sizeof *myvar);
typdef is intended to name a type
typedef enum { false, true } boolean;
boolean b = true; /* Yeah, C ANSI doesn't provide false/true keyword */
So here, you renamed the enum to boolean.
So when you write
typedef struct X {
//some field
} X;
You rename the type struct X to X. When i said rename, it's more an other name.
Tips, you can simply write :
typedef struct {
//some field
} X;
But if you need a field with the same type (like in a linked list) you had to give a name to your struct
typedef struct X {
X *next; /* will not work */
struct X *next; /* ok */
} X;
Hope this helps :)
Edit :
As Keith Thompson said, typdef is intended to create alias :)

Compiler: "error: dereferencing pointer to incomplete type" in thread application

Its my first publication and I'm studying C programming right now so I'm not an expert.
I've encountered that error compiling this lines (in a thread):
...
struct task_par *tp;
tp = (struct task_par *)arg;
a = tp->arg;
...
struct task_par is:
typedef struct
{
int arg;
int period;
int priority;
} task_par;
Note that "arg" is the argument of the thread
What's the correct type of "a"? because I've tried every type and it's still "error", so what else is wrong?
You don't define a struct task_par with the code you have shown. What you are defining is a typedef (a sort of new type) named task_par that is an alias for a certain anonymous struct type.
Your variable definition should simply say task_par *tp; in this case. If you prefer to use struct task_par, the way you have it now, you should change your struct definition to:
struct task_par
{ // ...
}
Or you can combine the two:
typedef struct task_par
{ // ...
} task_par_t;
Then you could define your variable either as struct task_par *tp; or as task_par_t *tp;.
The bottom line is that struct names and typedef names live in two different namespaces. You could even do typedef struct foo { /* */ } foo;, but some consider that bad form due to the potential for confusion...

using C struct that is declared later

I want use a typedef struct that isn't already defined, but it is later.
Is there anything like a struct prototype?
file container.h
// i would place a sort of struct prototype here
typedef struct
{
TheType * the_type;
} Container;
file thetype.h
typedef struct {......} TheType;
file main.c
#include "container.h"
#include "thetype.h"
...
Replace this line:
// i would place a sort of struct prototype here
with these lines:
struct TheType;
typedef struct TheType TheType;
Since you need the type TheType to be defined before type Container is defined, you have to use forward declaration of type TheType - and to do so you also need forward declaration of struct TheType.
Then you will not define typedef TheType like this:
typedef struct {......} TheType;
but you will define struct TheType:
struct {......};
In container.h:
struct _TheType;
typedef struct _TheType TheType;
Than in thetype.h:
struct _TheType { ..... };
You can declare a struct inside the typedef:
typedef struct TheType_Struct TheType; // declares "struct TheType_Struct"
// and makes typedef
typedef struct
{
TheType * p;
} UsefulType;
Note though that you may only have at most one typedef in one translation unit in C89 and C99 (this differs from C11 and C++).
Later on you must define the actual struct TheType_Struct { /* ... */ }.
You cannot define an object of an, as yet, undefined struct; but you can define a pointer to such a struct
struct one {
struct undefined *ok;
// struct undefined obj; /* error */
};
int foo(void) {
volatile struct one obj;
obj.ok = 0; /* NULL, but <stddef.h> not included, so 0 */
if (obj.ok) return 1;
return 0;
}
The above module is legal (and compiles with gcc without warnings).

Typedef of structs

I am using structs in my project in this way:
typedef struct
{
int str1_val1;
int str1_val2;
} struct1;
and
typedef struct
{
int str2_val1;
int str2_val2;
struct1* str2_val3;
} struct2;
Is it possible that I hack this definition in a way, that I would use only types with my code, like
struct2* a;
a = (struct2*) malloc(sizeof(struct2));
without using keyword struct?
Yes, as follows:
struct _struct1
{
...
};
typedef struct _struct1 struct1;
struct _struct2
{
...
};
typedef struct _struct2 struct2;
...
struct2 *a;
a = (struct2*)malloc(sizeof(struct2));
Yes, you can use the typedef'ed symbol without needing the struct keyword. The compiler simply uses that name as an alias for the structure you defined earlier.
One note on your example, malloc returns a pointer to memory. Hence your statement should read
a = (struct2 *)malloc(sizeof(struct2));
Just to share, I've seen this approach, and though I personally don't like it (I like everything named and tagged =P and I don't like using variable names in malloc), someone may.
typedef struct {
...
} *some_t;
int main() {
some_t var = (some_t) malloc(sizeof(*var));
}
as a footnote. If you code in C++ then you don't need to do the typedef; a struct is a type automatically.

Resources