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;
Related
Hi I was triying to make something like this, but I cant sort it out. The problem is one typedef needs the other one. I would really appreciate someones help!
#ifndef SHELL_DATA_H
#define SHELL_DATA_H
#include <buffer.h>
#define COMMANDS 10
#define MAX_ARGS 4
typedef struct {
void (*command)(int, char **, t_shellData *shelldData);
char *name;
char *description;
} t_command;
typedef struct {
t_command commands[COMMANDS];
t_buffer buffer;
char username[BUFFER_SIZE];
} t_shellData;
#endif
typedef struct command t_command;
typedef struct shelldata t_shellData;
struct command {
void (*command)(int, char **, t_shellData *shelldData);
char *name;
char *description;
};
struct shelldata {
t_command commands[COMMANDS];
t_buffer buffer;
char username[BUFFER_SIZE];
};
should fix it up for you. The structure tag and typedef name can be the same; I just renamed them for clarity.
C is a simple language, with an underlying principle of do not surprise people. For this reason, entities in C need to be declared or defined before they are used. As a simple example:
int f() {
int a = 7;
int b = a;
....
}
is OK, but this is not:
int f() {
int b = a;
int a = 7;
....
}
and while not exactly, languages like golang permit this -- the compiler will root around and find the definition you obviously wanted.
Typedef, in C, really just puts an entry into the symbol table; it is like a define, but less blunt, so the line:
typedef struct a A;
Serves to inform the compiler of two things: somewhere there is a structure with tag a, and I want A to be a shortform for it. There is another form of this:
struct a;
typedef struct a A;
Here, the first line tells the compiler "I want you to know about a thing called struct a"; and the second line "I want an alias to that struct a thing called A".
So, as the compiler progresses through the source, it knows that an A means a struct a, and even if it hasn't seen the definition of struct a, it has a placeholder.
But, if you attempted, before defining struct a to define another structure:
struct b {
struct a stuff;
int morestuff;
};
The compiler would complain, because it doesn't know the layout of a struct a; however this:
struct b {
struct a *stuff;
int morestuff;
};
is OK, because it knows how big a pointer is, and can defer its understanding of a struct a until it needs it.
So, Summary: declare or define data types before you attempt to use them. The C compiler requires it. A declaration is ok, unless you need the actual layout of it, in which case a definition is required.
Good Luck.
I'm trying to manually implement a polymorphic behavior in C by creating a generic struct, and then derived structs (if you will) which can be told apart by the value of an enum, so that I can have a pointer to the generic type, dereference it as the generic type, figure out what type it is, and then dereference it as the more specific type.
typedef struct{
enum type structType;
//... other stuff all the structs share
}generic;
typedef struct{
generic; //does not work, obviously, nor does (generic){};
//... other stuff unique to struct type A
}typeA;
I understand that I could just declare a named instance of the generic struct in the derived struct, but this seems a little messy, and I would prefer not to if there's a neat and tidy way around it.
You can't always get what you want, but if you try sometimes, well, you might find, you get what you need ...
There are two basic ways, with a slight bit of trickery:
Using an include file (e.g.): generic.h
Using a CPP macro (e.g): GENERIC
I've used both methods at various times.
Here's the method with the include file (generic.h):
enum type structType;
int com_fd;
void *com_buf;
And, here's a .c file that uses it:
typedef struct {
#include <generic.h>
} generic;
typedef struct {
#include <generic.h>
// other stuff unique to struct type A ...
int typea_value;
} typeA;
Here's the method using a macro:
#define GENERIC \
enum type structType; \
int com_fd; \
void *com_buf
typedef struct {
GENERIC;
} generic;
typedef struct {
GENERIC;
// other stuff unique to struct type A ...
int typea_value;
} typeA;
Can you declare an anonymous instance of a named struct?
No.
Yet code can make-up a name based on the line number, to keep it unique and with some level of animosity.
Now code should not try to reference var.member11 as the member's name changes as the code for typeA definition moves about in the file.
#define ANON_1(A,B) A##B
#define ANON_2(A,B) ANON_1(A,B)
#define ANON ANON_2(member, __LINE__)
typedef struct{
int x;
} generic;
typedef struct{
generic ANON; // name will be something like: member10
generic ANON; // name will be something like: member11
int y;
} typeA;
int main() {
typeA var;
(void) var;
return 0;
}
I suspect though to achieve OP's higher goal, a better approach is possible.
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;
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];
UPDATE: Code is correct and sensible, comments provide how to assign values to struct variables
I am writing a struct in C that contains 2 integer arrays and an array of custom-defined type 'info'. This 'info' type just contains several int variables. Here is the piece of code that I've come up with having done a bit of searching around the web:
typedef struct info {
int test_count;
int skip_count;
int prime_count;
} info;
struct myStruct {
int arr1[10];
int arr2[20];
info info[20];
};
This does not generate any compiler warnings or errors, but is it the most sensible implementation given what I'm trying to do?
Also– How would I assign values to the info variables and then access them through myStruct? I've tried various statements using the dot operator, but I cannot get them past the compiler.
Looks OK to me. Example usage struct myStruct x; x.info[3].skip_count = 4;
– M.M
And given: struct myStruct x; you should be able to use x.info[13].prime_count to access an element of that array.
– Jonathan Leffler