C90 and typedef - c

I had struct point {(...)}; defined. But with C90 it seems I have to do it with typedef. How do I do this correctly? typedef struct point {} point;? typedef struct {} point;? typedef struct point {};?

You can do:
typedef struct Point { ... } MyPoint;
and then use both kinds of declarations:
struct Point p1;
MyPoint p2;

Both of these are correct:
typedef struct point { /* ... */ } point;
typedef struct { /* ... */ } point;
The first version defines struct point and then defines point as an alias for it, while the second defines point as an alias for an anonymous struct.

Related

How to define a typedef struct inside another one with anonymous union? [duplicate]

This question already has answers here:
What is 'forward declaration' and the difference between 'typedef struct X' and 'struct X'?
(5 answers)
Closed 3 years ago.
I want to represent a nested ast node
typedef struct ast_assignment
{
char* sym;
ast_node* value;
} ast_assignment;
typedef struct ast_conjunction
{
char* sym;
ast_node* value;
} ast_conjunction;
typedef struct ast_node {
int node_type;
union {
ast_assignment data;
ast_conjunction data;
};
} ast_node;
but no matter what I define first, the compiler tells me that the other struct is an unknown type? How to proceed?
Typedef has to describe an actual type name
Typedefs require a ; after them
Circular type references require a bit of special sauce
Unions require different member names
Might you mean:
struct ast_node; // forward declaration
typedef struct {
char* sym;
struct ast_node* value;
} ast_assignment;
typedef struct ast_conjunction {
char * sym;
struct ast_node* value;
} ast_conjunction;
typedef struct ast_node {
int node_type;
union {
ast_assignment data_asg;
ast_conjunction data_conj;
};
} ast_node;
Expanding on this a bit for a more complete answer.
First, the purpose of a typedef is to install a new name into the compiler that you can use, so typedef struct { ... }; doesn't really do much. It should be typedef struct {...} newtype; so you can use that actual name newtype.
It also requires a semicolon after, which messes me up every time I go back from C# to C :-)
The circular reference thing is tricky, and doing struct mytype; in advance means you can use that name mytype only if it's in a context where knowledge of the structure details don't have to be known. In practice, it means you can use the struct mytype * as a pointer - because this is a fixed size - but this is not allowed:
struct ast_node; // forward declaration
struct some_other_type {
struct ast_node *nodeptr; // this is ok
struct ast_node thisnode; // FAIL
...
};
The reason is: a pointer is a fixed size no matter what kind of data it points to so the compiler carries you a bit, but the thisnode would require knowledge of all the details. Sorry, no way to do that.
Re: the union, you can't define any union or struct with two members with the same name because how could you reference one of them and the compiler would know which?
Personally I'm not a fan of using typedef for structure types, so I'd do this as:
struct ast_node; // forward struct defn
struct asg_assignment {
char *sym;
struct ast_node *value;
};
struct ast_conjunction {
char * sym;
struct ast_node* value;
};
struct ast_node {
int node_type;
union {
struct ast_assignment data_asg;
struct ast_conjunction data_conj;
};
};
... but I'm not sure I can justify this by anything other than personal preference.
You have multiple errors in your code. The correct way to declare a struct is as follows:
struct a {
...
}; // needs a semicolon
And to refer to it, you must use the struct keyword as well;
struct b {
struct a data;
};
In your case, the proper code that will compile is:
struct ast_assignment
{
char* sym;
struct ast_node* value;
};
struct ast_conjunction
{
char* sym;
struct ast_node* value;
};
struct ast_node {
int node_type;
union {
struct ast_assignment data_assignment;
struct ast_conjunction data_conjunction; // you cannot have multiple members with the same name
};
};
In C, the type you want to caƶl has to be declared first.
However, you can just use another pointer like void*.
void* is a pointer that can be used for any type.
If you define type of the later struct in the first struct as void*, the compiler will allow it.
But this has drawbacks. You are losing type safety with this and you may need to cast at some points.
Also, a typedef shortcut does not allow it to be used before the whole the typedef is declared.
This means, you can't use the shortcut inside the struct.
For example, the following would not be possible:
typedef struct mystruct{
myStruct_t *myValue;
} myStruct_t;
You'll need to do this instead:
typedef struct mystruct{
struct myStruct *myValue;
} myStruct_t;

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;

Pointer typecasting in c

I am writing an implementation of graphs in C language. I came across a situation where I am not able to figure out the reason for the way the compiler is behaving with a pointer typecast warning.
Here are the structures;
#define MAXV 10
typedef struct {
int y;
int weight;
struct edgenode *next;
} edgenode;
typedef struct {
edgenode *edge[MAXV+1];
int degree[MAXV+1];
// other info of graph
} graph;
// operation in some other function
p->next = g->edge[x];
I got a pointer typecast warning[enabled by default] when I do this kind of operation.
I was not able to remove this warning even after trying to typecast with every possible cast.
Finally I made a code change in the structure and suddenly the warning was gone.
The structure code change was this:-
typedef struct edgenode { // note that I have added structure name here
// same as above definition
} edgenode;
// operation in some other function
p->next = g->edge[x];
Now the warning is gone and code runs without any warnings.
I do not understand why is this happening; can anybody help me with this problem?
The problem is here:
typedef struct {
int y;
int weight;
struct edgenode *next;
} edgenode;
It is not clear what type struct edgenode *next; is referring to (it doesn't matter; somewhere, presumably, there's a struct edgenode defined), but it is not this structure because it has no tag. You need:
typedef struct edgenode
{
int y;
int weight;
struct edgenode *next;
} edgenode;
Now the pointer refers to another structure of this same type. So, the fix you found was the correct fix for your problem.
Remember: a typedef is an alias (alternative name) for an existing type. You created a type name edgenode, but you had not defined the type struct edgenode. You don't have to fully define a structure type before you create pointers to it; this can be a good way of creating 'opaque types'.
The other way to define things is:
typedef struct edgenode edgenode;
struct edgenode
{
int y;
int weight;
edgenode *next;
};
This says that the type name edgenode is an alias for a struct edgenode; the structure definition then tells the compiler what a struct edgenode looks like.

Using a struct in a header file "unknown type" error

I am using Kdevelop in Kubuntu.
I have declared a structure in my datasetup.h file:
#ifndef A_H
#define A_H
struct georeg_val {
int p;
double h;
double hfov;
double vfov;
};
#endif
Now when I use it in my main.c file
int main()
{
georeg_val gval;
read_data(gval); //this is in a .cpp file
}
I get the following error:
georeg_chain.c:7:3: error: unknown type name 'georeg_val'
(This is in the georeg_val gval; line)
I would appreciate if anyone could help me resolve this error.
In C one has two possibilities to declare structure:
struct STRUCT_NAME {} ;
or
typedef struct {} STRUCT_ALIAS;
If you use first method (give struct a name) - you must define variable by marking it explicitly being a struct:
struct STRUCT_NAME myStruct;
However if you use second method (give struct an alias) then you can omit struct identifier - compiler can deduce type of variable given only it's alias :
STRUCT_ALIAS myStruct;
Bonus points:
You can declare struct with both it's name and alias:
typedef struct STRUCT_TAG {} STRUCT_TAG;
// here STRUCT_NAME == STRUCT_ALIAS
Then in variable definition you can use either first or second method. Why both of two worlds is good ? Struct alias lets you to make struct variable definitions shorter - which is a good thing sometimes. But struct name let's you to make forward declarations. Which is indispensable tool in some cases - consider you have circular references between structs:
struct A {
struct B * b;
}
struct B {
struct A * a;
}
Besides that this architecture may be flawed - this circular definition will compile when structs are declared in the first way (with names) AND struct pointers are referenced explicitly by marking them as struct.
If you have to define a new type, you have to write:
typedef struct {
int p;
double h;
double hfov;
double vfov;
} georeg_val ;
Then you can use georeg_val as a new type.
Defining a struct type (on this example, a binary search tree struct):
struct tree {
int info;
struct tree *left;
struct tree *right;
}
typedef struct tree treeNode;
Declaring a function eg.:
treeNode *insertElement(treeNode *treeA, int number);

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).

Resources