Variations of struct definitions in C - c

I have built a struct in two ways, see below (Fig. A & Fig. B). In my .c file I access the struct like so (Fig. C).
Can someone please explain why Figure A makes a compiler error when accessed by Fig. C. Also, why Figure B doesn't cause a compiler error when accessed using Fig. C? Fig.
I can appreciate the syntax, if the struct is being used inside itself, the name needs to be in two places, top and bottom of struct.
Is it related to a 'forward reference' of sorts for the compiler? A good explanation would be appreciated.
//Fig. A
typedef struct
{
uint32_t* block_address;
struct mem_table_entry_t* next_entry_ptr;
}mem_table_entry_t;
typedef struct
{
mem_table_entry_t two_kib[8];
}mem_table_t;
and
//Fig. B
typedef struct mem_table_entry_t
{
uint32_t* block_address;
struct mem_table_entry_t* next_entry_ptr;
}mem_table_entry_t;
typedef struct
{
mem_table_entry_t two_kib[8];
}mem_table_t;
...
//Fig. C
memory_table.two_kib[block].next_entry_ptr = &memory_table.two_kib[block+1];

In snippet A, there is no struct mem_table_entry_t defined [yet] in the struct tag namespace. So you cannot refer to it as in struct mem_table_entry_t* next_entry_ptr;.
Your snippet B is correct.
Note also that the typedef namespace is distinct from the struct tag namespace. This means the the following are not compatible:
mem_table_entry_t two_kib1[8];
struct mem_table_entry_t two_kib2[8];

Related

What is purpose for different ways of naming of typedef statement?

I've the question about typedef statement.
Here is the code how i always write this statement:
typedef struct name
{
}name_t;
And here is the another example how i can write that:
typedef struct
{
}name;
Question is: what is purpose of that ways?
You need to use the first format if you have to refer to the type before the typedef is completed. This is necessary if the structure contains a pointer to the same type. This comes up when defining linked lists.
typedef struct name
{
int value;
struct name *next;
}name_t
You can't use name_t *next; inside the structure declaraction, because name_t isn't defined until later.
typedef struct name
{
}name_t;
name here is a struct tag and superfluous for the normal use-case, since you end up with a typedef anyhow and should only use name_t in your code from there on.
The only reason you'd add a tag there is the special case where you need a self-referencing struct such as a struct name* next; member in a linked list or such. In such cases we have to use the struct tag since the typedef name cannot be used before the typedef statement itself is done. Another alternative to that is to forward declare the struct.
The _t naming is industry standard way of naming types since the dawn of time. Unfortunately, the POSIX standard had the misguided idea to disallow such naming, so if you care about POSIX compliance, you should not name your types with _t in the end. If you don't care about POSIX, you should use _t because it gives proper, self-documenting code.
typedef struct name
{
int a;
double b;
char c;
}name_t;
name is a structure tag while name_t is a new type created by typedef.
To provide a structure tag explicitly is useful, if:
You want to implement a forward-declaration of the structure for use it in f.e. function definitions or other structures before the structure definition occurs (important if you have several translation units/C files).
For example:
File1.c
struct name; // forward declaration of structure `name`.
void foo(struct name *ptr)
{
....
}
struct bar
{
int x;
struct name y;
}
File2.c
typedef struct name
{
int a;
double b;
char c;
}name_t;
You want to define a pointer to an object of the structure itself inside of the structure, like required by linked lists:
typedef struct name
{
int a;
double b;
char c;
struct name *next;
}name_t;

How do you link (reference) a member of a structure using Doxygen?

I would like to "link" to a structure or member of a structure in Doxygen while displaying the text struct.member. My source code is in C.
For example, let's say I have the myStruct type/structure in C:
typedef struct
{
int member1;
int member2;
} myStruct;
And I would like to link/redirect within my Doxygen comments to documentation on myStruct while showing the text "myStruct.member1"
Example Doxygen Comments for a function:
You will receive the error code MEMBER_1_NOT_VALID if myStruct.member1 is larger than 5.
Where clicking on "myStruct.member1" redirects me to the documentation for myStruct.
I know that if I just have myStruct I could say "\ref myStruct", but doing "\ref myStruct.member1" does not work. Does anyone know how to make the documentation references work?
Any help is appreciated! Thank you.
I think the problem is that you defined the type and the structure together. Doxygen's parser seems to have problems with the mixed declaration of a struct and a typedef. Try to define the structure and the type definition seperately:
struct myStruct_s
{
int member1;
int member2;
};
typedef struct myStruct_s myStruct;
The you can reference the struct members using the tag name of the struct similar to as you already tried:
/**
* ...
* You will receive the error code MEMBER_1_NOT_VALID if \ref myStruct_s.member1
* is larger than 5.
* ...
*/

Structure declaration in c with identifer

I am try to understand this C code:
typedef struct _IntElem *IntList;
typedef struct _IntElem { int head; IntList tail;} IntElem;
I understand that it defines a recursive type, a list. However I don't understand the way it is declared. What I understand is the second line, we define a structure named IntElem which consists of an integer and an IntList. But what is the _IntElem in this declaration?
The first line allocates memory for the list?
The first line
typedef struct _IntElem *IntList;
is to just create a typedef or an alias for struct _IntElem *. The alias is named IntList. FWIW, at this point of time, the definition of struct _IntElem need not to be known to the compiler.
The second line
typedef struct _IntElem { int head; IntList tail;} IntElem;
Actually defines an user-defined type _IntElem, with two members, head as int and tail as IntList(typedefed earlier)
typedef the type to IntElem.
Please Note: There is actually no variable created, for either of the type (s) (I'm not talking about the member variables, of course, they are part of the definition). So, there is no memory allocated , as such.
So, to be explicit
But what is the _IntElem in this declaration?
the _IntElem is the name of the user-defined data type. However, in some cases, it is optional. for example,
typedef struct { char name [32]; int age; float salary;} employee;
is both perfectly fine and legal, except the fact, in this case, we're creating an alias employee to an unnamed data type.
In C, if we have:
struct X
{
stuff....
};
then X is called a struct tag. It means that struct X is the name of a type. X on its own is not the name of a type. In fact X on its own behaves like any other undeclared identifier; this struct definition only defines the specific usage struct X.
We might say that struct tags live in a different namespace to other identifiers (not to be confused with C++ namespaces!)
Sometimes people don't like typing struct X everywhere. So they use typedef (which, confusingly, means to create a type alias) in order to make a single identifier that names the type:
typedef struct X SX;
means that SX is a type. But since struct tags are in their own namespace, you could even write:
typedef struct X X;
which means that X on its own refers to the same type as struct X does.
Hopefully you understand the code you are looking at now. I think it would have been clearer to write:
struct IntElem
{
int head;
struct IntElem *tail;
};
with the optional addition to save typing:
typedef struct IntElem IntElem;
Pointer typedefs are evil, so IntList can be omitted entirely. Possibly you could keep it around to use as an opaque type for the users of your list, but you should avoid using it during your list implementation.

c put typedef into struct

I have a question about combining typedef and struct
I want to have a struct st, containing an enum e with elements i.e. {A,B,C}.
Later in my code, I want be able to write:
st.e=A;
One possibility is to write following code into a header file
typedef enum _enumDef{A,B,C} enumDef;
typedef struct _structDef{
enumDef e;
...
}structDef;
and then in my c-file I type structDef st and st.e=A
Now my question is, can I also write something like:
typedef struct _structDef{
typedef enum _enumDef{A,B,C} enumDef e;
...
}structDef;
? This one above doesn't work. But it is possible, to write
tyedef struct _structDef{
enum _enumDef{A,B,C} e;
...
}structDef;
but then I could not write st.e=A because the enum isn't known as global argument. Instead I have to write st.e=st.A
So my question is, is there any possibility, to include the typedef into the struct? I think, it looks nicer and it it easier to understand, from which context the enum is from. Or this this total unusual and I should clear it from my mind :D ?
Thanks
is there any possibility, to include the typedef into the struct?
storage class specifiers is not allowed within a structure as per C standard.
So you can't have a typedef member within structure
If you think of the {} in the struct as defining a scope it tells you that everything within those brackets is local to the struct and putting a typedef in there wouldn't add much even if the C language allowed you to do it.
(Inventing a conceptual namespace implementation might give some kind of structDef::enumDef syntax, but that's not part of C.)
If you need to use the enumeration type outside of the struct then it should be typedef'd outside the struct. The first example you give is the correct usage.
I will answer this question
Now my question is, can I also write something like:
typedef struct _structDef{
typedef enum _enumDef{A,B,C} enumDef e;
... }structDef; ?
I will give you the similarity so you can see the problem
when you want to create an int
you write
int a,b,c;
so int is the type and a b c are variable
typedef int a,b,c;
Now you can create other variable with type int via the tag a or b or c so
a variable1; //is the same as ==> int variable1;
b variable2; //is the same as ==> int variable2;
c variable3; //is the same as ==> int variable3;
let's return to our problem when take a look at this below to see the syntax and the similarity
enum _enumDef{A,B,C} e;
|------------------|
|
|------------------|
int e;
In order to create many varibales you need to add commas like in int
enum _enumDef{A,B,C} a,b,c;
|------------------| |----|
| |---->variables;
|------------------| |----|
int a,b,c;
the problem here
typedef enum _enumDef{A,B,C} enumDef e;
|--------|
|-------> no comma (ERROR)
is there is no comma between the two SAME tags (e and enumDef) and that's why it generates the problem !!
In order to make it work just add the comma between the same two tags e and enumDef of structure enum _enumDef {...}:
typedef enum _enumDef{A,B,C} enumDef, e;

typedef vs. no typedef with structs and enums in C

In C, is there any effective difference between declaring a struct as
typedef struct {...} Foo;
and
struct Foo {...};
I know the second requires you to prefix uses with struct, but what are the differences between these two definitions that I'll notice when writing or executing the program? What about with enums?
Update: please see comments attached to answer for clarification.
Original post.
Besides having to write "struct" everywhere, something else of note is that using a typedef will allow you to avoid subtle syntax errors when working with pointers:
Quote:
Typedefs can also simplify declarations for pointer types. Consider
this:
struct Node {
int data;
struct Node *nextptr;
};
Using typedef, the above code can be rewritten like this:
typedef struct Node Node;
struct Node {
int data;
Node *nextptr;
};
In C, one can declare multiple variables of the same type in a single
statement, even mixing pointer and non-pointers. However, one would
need to prefix an asterisk to each variable to designate it as a
pointer. In the following, a programmer might assume that errptr was
indeed a Node *, but a typographical error means that errptr is a
Node. This can lead to subtle syntax errors.
struct Node *startptr, *endptr, *curptr, *prevptr, errptr, *refptr;
By defining a Node * typedef, it is assured that all the variables
will be pointer types.
typedef struct Node *NodePtr;
...
NodePtr startptr, endptr, curptr, prevptr, errptr, refptr;
If you write
typedef struct {...} foo;
It saves you from having to write struct foo everywhere: you can just write foo.
(You get this notational convenience for free in C++ by the way).
I would look at this SO question and then summarize that there is no appreciable functional difference between struct { ... } and typedef struct { ... } although the latter may make your code less cumbersome and easier to understand if used correctly.

Resources