First, from this:
static struct foo1 { //private struct, just for this file
int a;
};
int main (void) {
struct foo1 a = {10};
return 0;
}
question number 1
I will get warning:
warning: useless storage class specifier in empty declaration
};
What does it mean? Why is static "useless storage class specifier"? In other context (static local var in function, or global static, which I wanted to apply for the struct foo1, it would work).
question number 2
#include <stdbool.h>
static struct s_t{ //private struct (for this file only)
static bool is_there = false; // defaul (pre-defined) value for all instances
int value;
};
int main (void) {}
Why is not possible to have static, predefined value for all vars of type struct s_t in c? I just wanted to simulate the same functionality as is in function static local var -> preserve value across multiple calls, in that sense, I wanted have one member (bool is_there in this case) that preserve value across each var of type struct foo1 (instance of it). So why it is not possible?
question number 3
Also, can someone explain the error (in more general sense) from it:
error: expected specifier-qualifier-list before ‘static’
EDIT:
from comments, I do not really understand the concept of storage class, I know only from asm, there is data/text/bss segments, so does it mean static var has address in read-only part of memory? Or what is the concept of storage class in c related to asm?
Because static struct foo1 { ... is just a struct definition, not a variable. You should add static when you declare the instance of the struct. I prefer this style:
typedef struct {
int a;
}foo_t;
static foo_t a = {10};
Because C simply doesn't have static member variables like C++ does. In C, it's pretty useless to add storage- or type specifiers to a single struct member. Put it on the allocated variables instead.
TL;DR it's just not making any sense of your syntax since you can't have static there. Unless you are terribly interested about language grammar, there's nothing else to it.
static is a storage-class specifier and const etc are type qualifiers and int etc is a type specifier. The term specifier-qualifier list comes from formal C grammar of structs, which isn't terribly interesting to read unless you are making a compiler. When declaring a struct member you have two options (C17 6.7.2.1):
specifier-qualifier-list:
type-specifier specifier-qualifier-list(opt)
type-qualifier specifier-qualifier-list(opt)
static doesn't fit the bill of either, being a storage-class specifier, so the compiler is saying "what! this is not a specifier-qualifier list where I expected to find one, where is it?"
(And yeah it's recursive, so you can have multiple of type-specifier or type-qualifier such as const long const const int value;. Because C stands for Crazy.)
because struct is like a type or an object, when you declare a static member in C, it would be like:
static int a = 0;
In this case "int" is like the struct type you declared, so if you want to create a struct static member just do like this:
static s_t a;
static struct foo1 { //private struct, just for this file
int a;
};
The static declaration specifier only applies to object or function declarations, not type definitions. All you're doing in that statement is creating the struct foo1 type. Had you written something like
static struct foo1 {
int a;
} foo;
Then the object foo would be declared static.
If you declare the type within the .c file, it will only be visible within that .c file. The only way to make the type visible to multiple .c files is to declare it in a header and #include that header in each file that needs it.
Why is not possible to have static, predefined value for all vars of type struct s_t in c?
Because C struct types are simply not that sophisticated - they're just a way to define a data item with multiple attributes. The language doesn't provide any way to have members that are common across all instances of the type.
Remember that C is a product of the early 1970s and was originally developed to implement the Unix operating system - it was designed to be small, portable, and fast. A lot's been added to it over the last 40-some-odd years, but nothing that really changes the core philosophy of the language.
Well, its quite evident that you will get the warning. The reason is simple! You are trying to assign a Storage Class to the struct definition.
However, storage classes are applicable to variable declarations. Therefore, you are getting the prompt.
If you still wish to employ the static storage class, then you can do so with any variable, preferably, any instance of the structure.
Related
Our professor provided us with two versions of a Complex Numbers program: a DT version and an ADT version.
The DT version contains various differences from the ADT one, but what I cannot grasp is whether it's important or not where the struct declaration is placed.
In the DT version the struct declaration has been placed in a header, along with the functions' declarations; in the ADT version it has been placed in a .c file, the one where the functions are written.
Is it important where the structure is placed? From what I can imagine it would work either way, but I'm not sure since I'm just getting started with the whole ADT concept. I can't see how the file the struct is placed in can damage information hiding.
If the fields of the type are declared in the header file, a client can access and modify the fields without going through the the functions which provide the interface to the module. One of the purposes of an abstract datatype is to be able to change the implementation, for instance the data representation, without affecting the client modules.
Is it important where the structure is placed?
If your program doesn't use any design but you just "hack away", then it doesn't matter. Otherwise if your program is larger and professional, it matters for the sake of private encapsulation, a key term used in object-oriented design.
In case you put the struct definition in the header file, the struct members are accessible to the code using the struct, it is fully public.
In case you only put a forward declaration of the struct in the header file, but the actual struct definition in the .c file, then you have achieved private encapsulation. Only the .c file can access the contents of the struct. This is often referred to as opaque type.
This in turn means that the caller won't be able to declare an object of that struct, because the definition is not visible to the caller. They can however declare a pointer to such a struct.
Simple example:
foo.h
typedef struct foo foo;
foo* foo_init (int x);
void foo_free (foo* f);
int foo_get_x (const foo* f);
foo.c
#include "foo.h"
struct foo
{
int x;
};
foo* foo_init (int x)
{
foo* f = malloc(sizeof *obj);
f->x = x;
return f;
}
void foo_free (foo* f)
{
free(f);
}
int foo_get_x (const foo* f)
{
return f->x;
}
caller.c
#include "foo.h"
foo* f = foo_init(123);
printf("%d", foo_get_x(f));
foo_free(f);
The second version (ADT) will not be visible from other translation units. So if in some translation unit there will be required a reference to the complete definition of the structure then the compiler will issue an error.
It seems that in the implementation of DT the correspomding functions refer to the ADT. So the definition of the ADT is only needed within the functions that deal with ADT. In this case there is nothing wrong.
Usualy when such an approach is used the functions defined for ADT are declared with internal linkage as static. And the functions for DT call internally the functions for ADT.
That is the definition of ADT and its functions are hidden and only visible for definitions of the functions for DT that refer the ADT and its functions.
I have seen many programs consisting of structures like the one below
typedef struct
{
int i;
char k;
} elem;
elem user;
Why is it needed so often? Any specific reason or applicable area?
As Greg Hewgill said, the typedef means you no longer have to write struct all over the place. That not only saves keystrokes, it also can make the code cleaner since it provides a smidgen more abstraction.
Stuff like
typedef struct {
int x, y;
} Point;
Point point_new(int x, int y)
{
Point a;
a.x = x;
a.y = y;
return a;
}
becomes cleaner when you don't need to see the "struct" keyword all over the place, it looks more as if there really is a type called "Point" in your language. Which, after the typedef, is the case I guess.
Also note that while your example (and mine) omitted naming the struct itself, actually naming it is also useful for when you want to provide an opaque type. Then you'd have code like this in the header, for instance:
typedef struct Point Point;
Point * point_new(int x, int y);
and then provide the struct definition in the implementation file:
struct Point
{
int x, y;
};
Point * point_new(int x, int y)
{
Point *p;
if((p = malloc(sizeof *p)) != NULL)
{
p->x = x;
p->y = y;
}
return p;
}
In this latter case, you cannot return the Point by value, since its definition is hidden from users of the header file. This is a technique used widely in GTK+, for instance.
UPDATE Note that there are also highly-regarded C projects where this use of typedef to hide struct is considered a bad idea, the Linux kernel is probably the most well-known such project. See Chapter 5 of The Linux Kernel CodingStyle document for Linus' angry words. :) My point is that the "should" in the question is perhaps not set in stone, after all.
It's amazing how many people get this wrong. PLEASE don't typedef structs in C, it needlessly pollutes the global namespace which is typically very polluted already in large C programs.
Also, typedef'd structs without a tag name are a major cause of needless imposition of ordering relationships among header files.
Consider:
#ifndef FOO_H
#define FOO_H 1
#define FOO_DEF (0xDEADBABE)
struct bar; /* forward declaration, defined in bar.h*/
struct foo {
struct bar *bar;
};
#endif
With such a definition, not using typedefs, it is possible for a compiland unit to include foo.h to get at the FOO_DEF definition. If it doesn't attempt to dereference the 'bar' member of the foo struct then there will be no need to include the "bar.h" file.
Also, since the namespaces are different between the tag names and the member names, it is possible to write very readable code such as:
struct foo *foo;
printf("foo->bar = %p", foo->bar);
Since the namespaces are separate, there is no conflict in naming variables coincident with their struct tag name.
If I have to maintain your code, I will remove your typedef'd structs.
From an old article by Dan Saks (http://www.ddj.com/cpp/184403396?pgno=3):
The C language rules for naming
structs are a little eccentric, but
they're pretty harmless. However, when
extended to classes in C++, those same
rules open little cracks for bugs to
crawl through.
In C, the name s appearing in
struct s
{
...
};
is a tag. A tag name is not a type
name. Given the definition above,
declarations such as
s x; /* error in C */
s *p; /* error in C */
are errors in C. You must write them
as
struct s x; /* OK */
struct s *p; /* OK */
The names of unions and enumerations
are also tags rather than types.
In C, tags are distinct from all other
names (for functions, types,
variables, and enumeration constants).
C compilers maintain tags in a symbol
table that's conceptually if not
physically separate from the table
that holds all other names. Thus, it
is possible for a C program to have
both a tag and an another name with
the same spelling in the same scope.
For example,
struct s s;
is a valid declaration which declares
variable s of type struct s. It may
not be good practice, but C compilers
must accept it. I have never seen a
rationale for why C was designed this
way. I have always thought it was a
mistake, but there it is.
Many programmers (including yours
truly) prefer to think of struct names
as type names, so they define an alias
for the tag using a typedef. For
example, defining
struct s
{
...
};
typedef struct s S;
lets you use S in place of struct s,
as in
S x;
S *p;
A program cannot use S as the name of
both a type and a variable (or
function or enumeration constant):
S S; // error
This is good.
The tag name in a struct, union, or
enum definition is optional. Many
programmers fold the struct definition
into the typedef and dispense with the
tag altogether, as in:
typedef struct
{
...
} S;
The linked article also has a discussion about how the C++ behavior of not requireing a typedef can cause subtle name hiding problems. To prevent these problems, it's a good idea to typedef your classes and structs in C++, too, even though at first glance it appears to be unnecessary. In C++, with the typedef the name hiding become an error that the compiler tells you about rather than a hidden source of potential problems.
Using a typedef avoids having to write struct every time you declare a variable of that type:
struct elem
{
int i;
char k;
};
elem user; // compile error!
struct elem user; // this is correct
One other good reason to always typedef enums and structs results from this problem:
enum EnumDef
{
FIRST_ITEM,
SECOND_ITEM
};
struct StructDef
{
enum EnuumDef MyEnum;
unsigned int MyVar;
} MyStruct;
Notice the typo in EnumDef in the struct (EnuumDef)? This compiles without error (or warning) and is (depending on the literal interpretation of the C Standard) correct. The problem is that I just created an new (empty) enumeration definition within my struct. I am not (as intended) using the previous definition EnumDef.
With a typdef similar kind of typos would have resulted in a compiler errors for using an unknown type:
typedef
{
FIRST_ITEM,
SECOND_ITEM
} EnumDef;
typedef struct
{
EnuumDef MyEnum; /* compiler error (unknown type) */
unsigned int MyVar;
} StructDef;
StrructDef MyStruct; /* compiler error (unknown type) */
I would advocate ALWAYS typedef'ing structs and enumerations.
Not only to save some typing (no pun intended ;)), but because it is safer.
Linux kernel coding style Chapter 5 gives great pros and cons (mostly cons) of using typedef.
Please don't use things like "vps_t".
It's a mistake to use typedef for structures and pointers. When you see a
vps_t a;
in the source, what does it mean?
In contrast, if it says
struct virtual_container *a;
you can actually tell what "a" is.
Lots of people think that typedefs "help readability". Not so. They are useful only for:
(a) totally opaque objects (where the typedef is actively used to hide what the object is).
Example: "pte_t" etc. opaque objects that you can only access using the proper accessor functions.
NOTE! Opaqueness and "accessor functions" are not good in themselves. The reason we have them for things like pte_t etc. is that there really is absolutely zero portably accessible information there.
(b) Clear integer types, where the abstraction helps avoid confusion whether it is "int" or "long".
u8/u16/u32 are perfectly fine typedefs, although they fit into category (d) better than here.
NOTE! Again - there needs to be a reason for this. If something is "unsigned long", then there's no reason to do
typedef unsigned long myflags_t;
but if there is a clear reason for why it under certain circumstances might be an "unsigned int" and under other configurations might be "unsigned long", then by all means go ahead and use a typedef.
(c) when you use sparse to literally create a new type for type-checking.
(d) New types which are identical to standard C99 types, in certain exceptional circumstances.
Although it would only take a short amount of time for the eyes and brain to become accustomed to the standard types like 'uint32_t', some people object to their use anyway.
Therefore, the Linux-specific 'u8/u16/u32/u64' types and their signed equivalents which are identical to standard types are permitted -- although they are not mandatory in new code of your own.
When editing existing code which already uses one or the other set of types, you should conform to the existing choices in that code.
(e) Types safe for use in userspace.
In certain structures which are visible to userspace, we cannot require C99 types and cannot use the 'u32' form above. Thus, we use __u32 and similar types in all structures which are shared with userspace.
Maybe there are other cases too, but the rule should basically be to NEVER EVER use a typedef unless you can clearly match one of those rules.
In general, a pointer, or a struct that has elements that can reasonably be directly accessed should never be a typedef.
It turns out that there are pros and cons. A useful source of information is the seminal book "Expert C Programming" (Chapter 3). Briefly, in C you have multiple namespaces: tags, types, member names and identifiers. typedef introduces an alias for a type and locates it in the tag namespace. Namely,
typedef struct Tag{
...members...
}Type;
defines two things. 1) Tag in the tag namespace and 2) Type in the type namespace. So you can do both Type myType and struct Tag myTagType. Declarations like struct Type myType or Tag myTagType are illegal. In addition, in a declaration like this:
typedef Type *Type_ptr;
we define a pointer to our Type. So if we declare:
Type_ptr var1, var2;
struct Tag *myTagType1, myTagType2;
then var1,var2 and myTagType1 are pointers to Type but myTagType2 not.
In the above-mentioned book, it mentions that typedefing structs are not very useful as it only saves the programmer from writing the word struct. However, I have an objection, like many other C programmers. Although it sometimes turns to obfuscate some names (that's why it is not advisable in large code bases like the kernel) when you want to implement polymorphism in C it helps a lot look here for details. Example:
typedef struct MyWriter_t{
MyPipe super;
MyQueue relative;
uint32_t flags;
...
}MyWriter;
you can do:
void my_writer_func(MyPipe *s)
{
MyWriter *self = (MyWriter *) s;
uint32_t myFlags = self->flags;
...
}
So you can access an outer member (flags) by the inner struct (MyPipe) through casting. For me it is less confusing to cast the whole type than doing (struct MyWriter_ *) s; every time you want to perform such functionality. In these cases brief referencing is a big deal especially if you heavily employ the technique in your code.
Finally, the last aspect with typedefed types is the inability to extend them, in contrast to macros. If for example, you have:
#define X char[10] or
typedef char Y[10]
you can then declare
unsigned X x; but not
unsigned Y y;
We do not really care for this for structs because it does not apply to storage specifiers (volatile and const).
I don't think forward declarations are even possible with typedef. Use of struct, enum, and union allow for forwarding declarations when dependencies (knows about) is bidirectional.
Style:
Use of typedef in C++ makes quite a bit of sense. It can almost be necessary when dealing with templates that require multiple and/or variable parameters. The typedef helps keep the naming straight.
Not so in the C programming language. The use of typedef most often serves no purpose but to obfuscate the data structure usage. Since only { struct (6), enum (4), union (5) } number of keystrokes are used to declare a data type there is almost no use for the aliasing of the struct. Is that data type a union or a struct? Using the straightforward non-typdefed declaration lets you know right away what type it is.
Notice how Linux is written with strict avoidance of this aliasing nonsense typedef brings. The result is a minimalist and clean style.
Let's start with the basics and work our way up.
Here is an example of Structure definition:
struct point
{
int x, y;
};
Here the name point is optional.
A Structure can be declared during its definition or after.
Declaring during definition
struct point
{
int x, y;
} first_point, second_point;
Declaring after definition
struct point
{
int x, y;
};
struct point first_point, second_point;
Now, carefully note the last case above; you need to write struct point to declare Structures of that type if you decide to create that type at a later point in your code.
Enter typedef. If you intend to create new Structure ( Structure is a custom data-type) at a later time in your program using the same blueprint, using typedef during its definition might be a good idea since you can save some typing moving forward.
typedef struct point
{
int x, y;
} Points;
Points first_point, second_point;
A word of caution while naming your custom type
Nothing prevents you from using _t suffix at the end of your custom type name but POSIX standard reserves the use of suffix _t to denote standard library type names.
The name you (optionally) give the struct is called the tag name and, as has been noted, is not a type in itself. To get to the type requires the struct prefix.
GTK+ aside, I'm not sure the tagname is used anything like as commonly as a typedef to the struct type, so in C++ that is recognised and you can omit the struct keyword and use the tagname as the type name too:
struct MyStruct
{
int i;
};
// The following is legal in C++:
MyStruct obj;
obj.i = 7;
typedef will not provide a co-dependent set of data structures. This you cannot do with typdef:
struct bar;
struct foo;
struct foo {
struct bar *b;
};
struct bar {
struct foo *f;
};
Of course you can always add:
typedef struct foo foo_t;
typedef struct bar bar_t;
What exactly is the point of that?
A>
a typdef aids in the meaning and documentation of a program by allowing creation of more meaningful synonyms for data types. In addition, they help parameterize a program against portability problems (K&R, pg147, C prog lang).
B>
a structure defines a type. Structs allows convenient grouping of a collection of vars for convenience of handling (K&R, pg127, C prog lang.) as a single unit
C>
typedef'ing a struct is explained in A above.
D> To me, structs are custom types or containers or collections or namespaces or complex types, whereas a typdef is just a means to create more nicknames.
In 'C' programming language the keyword 'typedef' is used to declare a new name for some object(struct, array, function..enum type). For example, I will use a 'struct-s'.
In 'C' we often declare a 'struct' outside of the 'main' function. For example:
struct complex{ int real_part, img_part }COMPLEX;
main(){
struct KOMPLEKS number; // number type is now a struct type
number.real_part = 3;
number.img_part = -1;
printf("Number: %d.%d i \n",number.real_part, number.img_part);
}
Each time I decide to use a struct type I will need this keyword 'struct 'something' 'name'.'typedef' will simply rename that type and I can use that new name in my program every time I want. So our code will be:
typedef struct complex{int real_part, img_part; }COMPLEX;
//now COMPLEX is the new name for this structure and if I want to use it without
// a keyword like in the first example 'struct complex number'.
main(){
COMPLEX number; // number is now the same type as in the first example
number.real_part = 1;
number.img)part = 5;
printf("%d %d \n", number.real_part, number.img_part);
}
If you have some local object(struct, array, valuable) that will be used in your entire program you can simply give it a name using a 'typedef'.
Turns out in C99 typedef is required. It is outdated, but a lot of tools (ala HackRank) use c99 as its pure C implementation. And typedef is required there.
I'm not saying they should change (maybe have two C options) if the requirement changed, those of us studing for interviews on the site would be SOL.
At all, in C language, struct/union/enum are macro instruction processed by the C language preprocessor (do not mistake with the preprocessor that treat "#include" and other)
so :
struct a
{
int i;
};
struct b
{
struct a;
int i;
int j;
};
struct b is expended as something like this :
struct b
{
struct a
{
int i;
};
int i;
int j;
}
and so, at compile time it evolve on stack as something like:
b:
int ai
int i
int j
that also why it's dificult to have selfreferent structs, C preprocessor round in a déclaration loop that can't terminate.
typedef are type specifier, that means only C compiler process it and it can do like he want for optimise assembler code implementation. It also dont expend member of type par stupidly like préprocessor do with structs but use more complex reference construction algorithm, so construction like :
typedef struct a A; //anticipated declaration for member declaration
typedef struct a //Implemented declaration
{
A* b; // member declaration
}A;
is permited and fully functional. This implementation give also access to compilator type conversion and remove some bugging effects when execution thread leave the application field of initialisation functions.
This mean that in C typedefs are more near as C++ class than lonely structs.
I have a question about the member variables of static struct in C language.
Someone said we can declare a static struct, but in C, struct do not have the static members like class in C++, what does this mean? If I declare a static struct, what is the status of the members variable? can some one help me on this?
Note that a static struct itself is different from a static member of a struct. While you can declare a static struct variable:
static struct MyStruct s;
you can't define a struct type with a static member:
struct MyStruct {
static int i; // <- compiler error
};
The reason for this is that in C, a struct is a type - declaring a type of which a member variable is always the same instance (i. e. static) for multiple instances of that type is simply nonsense. In C++, structs are in reality classes (they only differ in the default visibility scope of members), and in C++ the static keyword means something else in this case. It means a class method - but since C doesn't have classes and methods, this doesn't make sense and is invalid in C.
Lesson learned: C++ is not C.
static in C means:
There shall only be one instance of this variable in the program.
The variable should be valid throughout the whole duration of the program execution.
The variable shall be initialized before main() is executed. If the programmer initializes a variable explicitly, then it should be set to this value. Otherwise it should be set to zero.
The variable (or static function) shall only be accessible from the scope it is declared inside. If declared at file scope (global), then it is only accessible in the same .c file.
In C++, there is also one additional meaning:
A static member variable or member function shall only be allocated once, no matter how many instances of a class that are allocated.
I have a question about the member variables of static struct in C language.
Someone said we can declare a static struct
Correct/legal:
// (global scope)
static struct t_struct {
int a;
} THE_STATIC_VARIABLE;
but in C, struct do not have the static members like class in C++
// (global scope)
struct t_ill_struct {
static int a; // << ill-formed in C, but valid in C++
};
what does this mean? If I declare a static struct, what is the status of the members variable? can some one help me on this?
Using the above example, it means that THE_STATIC_VARIABLE will have static storage. The following are equivalent:
A
// (global scope)
static struct t_struct {
int a;
} THE_STATIC_VARIABLE;
B
// (global scope)
struct t_struct {
int a;
};
static struct t_struct THE_STATIC_VARIABLE;
That is to say, every translation which sees THE_STATIC_VARIABLE's definition will get its own copy.
If you want the same effect as a static C++ member, you will have to declare it in another scope -- outside of a struct's declaration:
// file.h
// (global scope)
struct t_struct {
int a;
};
extern struct t_struct THE_GLOBAL_VARIABLE;
// file.c
struct t_struct THE_GLOBAL_VARIABLE;
Now we really have exactly one, like in C++.
I've been using the following code to create various struct, but only give people outside of the C file a pointer to it. (Yes, I know that they could potentially mess around with it, so it's not entirely like the private keyword in Java, but that's okay with me).
Anyway, I've been using the following code, and I looked at it today, and I'm really surprised that it's actually working, can anyone explain why this is?
In my C file, I create my struct, but don't give it a tag in the typedef namespace:
struct LABall {
int x;
int y;
int radius;
Vector velocity;
};
And in the H file, I put this:
typedef struct LABall* LABall;
I am obviously using #include "LABall.h" in the c file, but I am NOT using #include "LABall.c" in the header file, as that would defeat the whole purpose of a separate header file. So, why am I able to create a pointer to the LABall* struct in the H file when I haven't actually included it? Does it have something to do with the struct namespace working accross files, even when one file is in no way linked to another?
Thank you.
A common pattern for stuff like that is to have a foo.h file defining the API like
typedef struct _Foo Foo;
Foo *foo_new();
void foo_do_something(Foo *foo);
and a foo.c file providing an implementation for that API like
struct _Foo {
int bar;
};
Foo *foo_new() {
Foo *foo = malloc(sizeof(Foo));
foo->bar = 0;
return foo;
}
void foo_do_something(Foo *foo) {
foo->bar++;
}
This hides all the memory layout and size of the struct in the implementation in foo.c, and the interface exposed via foo.h is completely independent of those internals: A caller.c which only does #include "foo.h" will only have to store a pointer to something, and pointers are always the same size:
#include "foo.h"
void bleh() {
Foo *f = foo_new();
foo_do_something(f);
}
Note: The ISO C standard section on reserved identifiers says that all identifiers beginning with an underscore are reserved. So typedef struct Foo Foo; is actually a better way to name things than typedef struct _Foo Foo;.
Note: I have left freeing the memory as an exercise to the reader. :-)
Of course, this means that the following file broken.c will NOT work:
#include "foo.h"
void broken() {
Foo f;
foo_do_something(&f);
}
as the memory size necessary for actually creating a variable of type Foo is not known in this file.
Since you're asking a precise reason as to "why" the language works this way, I'm assuming you want some precise references. If you find that pedant, just skip the notes...
It works because of two things:
All pointer to structure types have the same representation (note that it's not true of all pointer types, as far as standard C is concerned).[1] Hence, the compiler has enough information to generate proper code for all uses of your pointer-to-struct type.
The tag namespace (struct, enum, union) is indeed compatible accross all translation units.[2] Thus, the two structures (even though one is not completely defined, i.e. it lacks member declarations) are one and the same.
(BTW, #import is non-standard.)
[1] As per n1256 §6.2.5.27:
All pointers to structure types shall have the same representation and alignment requirements as each other. Pointers to other types need not have the same representation or alignment requirements.
[2] As per n1256 §6.2.7.1:
two structure, union, or enumerated types declared in separate translation units are compatible if their tags and members satisfy the following requirements: If one is declared with a tag, the other shall be declared with the same tag. If both are complete types, then the following additional requirements apply: [does not concern us].
In
typedef struct A* B;
since all pointers' interfaces are the same, knowing that B means a pointer to a struct A contains enough information already. The actual implementation of A is irrelevant (this technique is called "opaque pointer".)
(BTW, better rename one of the LABall's. It's confusing that the same name is used for incompatible types.)
I have seen many programs consisting of structures like the one below
typedef struct
{
int i;
char k;
} elem;
elem user;
Why is it needed so often? Any specific reason or applicable area?
As Greg Hewgill said, the typedef means you no longer have to write struct all over the place. That not only saves keystrokes, it also can make the code cleaner since it provides a smidgen more abstraction.
Stuff like
typedef struct {
int x, y;
} Point;
Point point_new(int x, int y)
{
Point a;
a.x = x;
a.y = y;
return a;
}
becomes cleaner when you don't need to see the "struct" keyword all over the place, it looks more as if there really is a type called "Point" in your language. Which, after the typedef, is the case I guess.
Also note that while your example (and mine) omitted naming the struct itself, actually naming it is also useful for when you want to provide an opaque type. Then you'd have code like this in the header, for instance:
typedef struct Point Point;
Point * point_new(int x, int y);
and then provide the struct definition in the implementation file:
struct Point
{
int x, y;
};
Point * point_new(int x, int y)
{
Point *p;
if((p = malloc(sizeof *p)) != NULL)
{
p->x = x;
p->y = y;
}
return p;
}
In this latter case, you cannot return the Point by value, since its definition is hidden from users of the header file. This is a technique used widely in GTK+, for instance.
UPDATE Note that there are also highly-regarded C projects where this use of typedef to hide struct is considered a bad idea, the Linux kernel is probably the most well-known such project. See Chapter 5 of The Linux Kernel CodingStyle document for Linus' angry words. :) My point is that the "should" in the question is perhaps not set in stone, after all.
It's amazing how many people get this wrong. PLEASE don't typedef structs in C, it needlessly pollutes the global namespace which is typically very polluted already in large C programs.
Also, typedef'd structs without a tag name are a major cause of needless imposition of ordering relationships among header files.
Consider:
#ifndef FOO_H
#define FOO_H 1
#define FOO_DEF (0xDEADBABE)
struct bar; /* forward declaration, defined in bar.h*/
struct foo {
struct bar *bar;
};
#endif
With such a definition, not using typedefs, it is possible for a compiland unit to include foo.h to get at the FOO_DEF definition. If it doesn't attempt to dereference the 'bar' member of the foo struct then there will be no need to include the "bar.h" file.
Also, since the namespaces are different between the tag names and the member names, it is possible to write very readable code such as:
struct foo *foo;
printf("foo->bar = %p", foo->bar);
Since the namespaces are separate, there is no conflict in naming variables coincident with their struct tag name.
If I have to maintain your code, I will remove your typedef'd structs.
From an old article by Dan Saks (http://www.ddj.com/cpp/184403396?pgno=3):
The C language rules for naming
structs are a little eccentric, but
they're pretty harmless. However, when
extended to classes in C++, those same
rules open little cracks for bugs to
crawl through.
In C, the name s appearing in
struct s
{
...
};
is a tag. A tag name is not a type
name. Given the definition above,
declarations such as
s x; /* error in C */
s *p; /* error in C */
are errors in C. You must write them
as
struct s x; /* OK */
struct s *p; /* OK */
The names of unions and enumerations
are also tags rather than types.
In C, tags are distinct from all other
names (for functions, types,
variables, and enumeration constants).
C compilers maintain tags in a symbol
table that's conceptually if not
physically separate from the table
that holds all other names. Thus, it
is possible for a C program to have
both a tag and an another name with
the same spelling in the same scope.
For example,
struct s s;
is a valid declaration which declares
variable s of type struct s. It may
not be good practice, but C compilers
must accept it. I have never seen a
rationale for why C was designed this
way. I have always thought it was a
mistake, but there it is.
Many programmers (including yours
truly) prefer to think of struct names
as type names, so they define an alias
for the tag using a typedef. For
example, defining
struct s
{
...
};
typedef struct s S;
lets you use S in place of struct s,
as in
S x;
S *p;
A program cannot use S as the name of
both a type and a variable (or
function or enumeration constant):
S S; // error
This is good.
The tag name in a struct, union, or
enum definition is optional. Many
programmers fold the struct definition
into the typedef and dispense with the
tag altogether, as in:
typedef struct
{
...
} S;
The linked article also has a discussion about how the C++ behavior of not requireing a typedef can cause subtle name hiding problems. To prevent these problems, it's a good idea to typedef your classes and structs in C++, too, even though at first glance it appears to be unnecessary. In C++, with the typedef the name hiding become an error that the compiler tells you about rather than a hidden source of potential problems.
Using a typedef avoids having to write struct every time you declare a variable of that type:
struct elem
{
int i;
char k;
};
elem user; // compile error!
struct elem user; // this is correct
One other good reason to always typedef enums and structs results from this problem:
enum EnumDef
{
FIRST_ITEM,
SECOND_ITEM
};
struct StructDef
{
enum EnuumDef MyEnum;
unsigned int MyVar;
} MyStruct;
Notice the typo in EnumDef in the struct (EnuumDef)? This compiles without error (or warning) and is (depending on the literal interpretation of the C Standard) correct. The problem is that I just created an new (empty) enumeration definition within my struct. I am not (as intended) using the previous definition EnumDef.
With a typdef similar kind of typos would have resulted in a compiler errors for using an unknown type:
typedef
{
FIRST_ITEM,
SECOND_ITEM
} EnumDef;
typedef struct
{
EnuumDef MyEnum; /* compiler error (unknown type) */
unsigned int MyVar;
} StructDef;
StrructDef MyStruct; /* compiler error (unknown type) */
I would advocate ALWAYS typedef'ing structs and enumerations.
Not only to save some typing (no pun intended ;)), but because it is safer.
Linux kernel coding style Chapter 5 gives great pros and cons (mostly cons) of using typedef.
Please don't use things like "vps_t".
It's a mistake to use typedef for structures and pointers. When you see a
vps_t a;
in the source, what does it mean?
In contrast, if it says
struct virtual_container *a;
you can actually tell what "a" is.
Lots of people think that typedefs "help readability". Not so. They are useful only for:
(a) totally opaque objects (where the typedef is actively used to hide what the object is).
Example: "pte_t" etc. opaque objects that you can only access using the proper accessor functions.
NOTE! Opaqueness and "accessor functions" are not good in themselves. The reason we have them for things like pte_t etc. is that there really is absolutely zero portably accessible information there.
(b) Clear integer types, where the abstraction helps avoid confusion whether it is "int" or "long".
u8/u16/u32 are perfectly fine typedefs, although they fit into category (d) better than here.
NOTE! Again - there needs to be a reason for this. If something is "unsigned long", then there's no reason to do
typedef unsigned long myflags_t;
but if there is a clear reason for why it under certain circumstances might be an "unsigned int" and under other configurations might be "unsigned long", then by all means go ahead and use a typedef.
(c) when you use sparse to literally create a new type for type-checking.
(d) New types which are identical to standard C99 types, in certain exceptional circumstances.
Although it would only take a short amount of time for the eyes and brain to become accustomed to the standard types like 'uint32_t', some people object to their use anyway.
Therefore, the Linux-specific 'u8/u16/u32/u64' types and their signed equivalents which are identical to standard types are permitted -- although they are not mandatory in new code of your own.
When editing existing code which already uses one or the other set of types, you should conform to the existing choices in that code.
(e) Types safe for use in userspace.
In certain structures which are visible to userspace, we cannot require C99 types and cannot use the 'u32' form above. Thus, we use __u32 and similar types in all structures which are shared with userspace.
Maybe there are other cases too, but the rule should basically be to NEVER EVER use a typedef unless you can clearly match one of those rules.
In general, a pointer, or a struct that has elements that can reasonably be directly accessed should never be a typedef.
It turns out that there are pros and cons. A useful source of information is the seminal book "Expert C Programming" (Chapter 3). Briefly, in C you have multiple namespaces: tags, types, member names and identifiers. typedef introduces an alias for a type and locates it in the tag namespace. Namely,
typedef struct Tag{
...members...
}Type;
defines two things. 1) Tag in the tag namespace and 2) Type in the type namespace. So you can do both Type myType and struct Tag myTagType. Declarations like struct Type myType or Tag myTagType are illegal. In addition, in a declaration like this:
typedef Type *Type_ptr;
we define a pointer to our Type. So if we declare:
Type_ptr var1, var2;
struct Tag *myTagType1, myTagType2;
then var1,var2 and myTagType1 are pointers to Type but myTagType2 not.
In the above-mentioned book, it mentions that typedefing structs are not very useful as it only saves the programmer from writing the word struct. However, I have an objection, like many other C programmers. Although it sometimes turns to obfuscate some names (that's why it is not advisable in large code bases like the kernel) when you want to implement polymorphism in C it helps a lot look here for details. Example:
typedef struct MyWriter_t{
MyPipe super;
MyQueue relative;
uint32_t flags;
...
}MyWriter;
you can do:
void my_writer_func(MyPipe *s)
{
MyWriter *self = (MyWriter *) s;
uint32_t myFlags = self->flags;
...
}
So you can access an outer member (flags) by the inner struct (MyPipe) through casting. For me it is less confusing to cast the whole type than doing (struct MyWriter_ *) s; every time you want to perform such functionality. In these cases brief referencing is a big deal especially if you heavily employ the technique in your code.
Finally, the last aspect with typedefed types is the inability to extend them, in contrast to macros. If for example, you have:
#define X char[10] or
typedef char Y[10]
you can then declare
unsigned X x; but not
unsigned Y y;
We do not really care for this for structs because it does not apply to storage specifiers (volatile and const).
I don't think forward declarations are even possible with typedef. Use of struct, enum, and union allow for forwarding declarations when dependencies (knows about) is bidirectional.
Style:
Use of typedef in C++ makes quite a bit of sense. It can almost be necessary when dealing with templates that require multiple and/or variable parameters. The typedef helps keep the naming straight.
Not so in the C programming language. The use of typedef most often serves no purpose but to obfuscate the data structure usage. Since only { struct (6), enum (4), union (5) } number of keystrokes are used to declare a data type there is almost no use for the aliasing of the struct. Is that data type a union or a struct? Using the straightforward non-typdefed declaration lets you know right away what type it is.
Notice how Linux is written with strict avoidance of this aliasing nonsense typedef brings. The result is a minimalist and clean style.
Let's start with the basics and work our way up.
Here is an example of Structure definition:
struct point
{
int x, y;
};
Here the name point is optional.
A Structure can be declared during its definition or after.
Declaring during definition
struct point
{
int x, y;
} first_point, second_point;
Declaring after definition
struct point
{
int x, y;
};
struct point first_point, second_point;
Now, carefully note the last case above; you need to write struct point to declare Structures of that type if you decide to create that type at a later point in your code.
Enter typedef. If you intend to create new Structure ( Structure is a custom data-type) at a later time in your program using the same blueprint, using typedef during its definition might be a good idea since you can save some typing moving forward.
typedef struct point
{
int x, y;
} Points;
Points first_point, second_point;
A word of caution while naming your custom type
Nothing prevents you from using _t suffix at the end of your custom type name but POSIX standard reserves the use of suffix _t to denote standard library type names.
The name you (optionally) give the struct is called the tag name and, as has been noted, is not a type in itself. To get to the type requires the struct prefix.
GTK+ aside, I'm not sure the tagname is used anything like as commonly as a typedef to the struct type, so in C++ that is recognised and you can omit the struct keyword and use the tagname as the type name too:
struct MyStruct
{
int i;
};
// The following is legal in C++:
MyStruct obj;
obj.i = 7;
typedef will not provide a co-dependent set of data structures. This you cannot do with typdef:
struct bar;
struct foo;
struct foo {
struct bar *b;
};
struct bar {
struct foo *f;
};
Of course you can always add:
typedef struct foo foo_t;
typedef struct bar bar_t;
What exactly is the point of that?
A>
a typdef aids in the meaning and documentation of a program by allowing creation of more meaningful synonyms for data types. In addition, they help parameterize a program against portability problems (K&R, pg147, C prog lang).
B>
a structure defines a type. Structs allows convenient grouping of a collection of vars for convenience of handling (K&R, pg127, C prog lang.) as a single unit
C>
typedef'ing a struct is explained in A above.
D> To me, structs are custom types or containers or collections or namespaces or complex types, whereas a typdef is just a means to create more nicknames.
In 'C' programming language the keyword 'typedef' is used to declare a new name for some object(struct, array, function..enum type). For example, I will use a 'struct-s'.
In 'C' we often declare a 'struct' outside of the 'main' function. For example:
struct complex{ int real_part, img_part }COMPLEX;
main(){
struct KOMPLEKS number; // number type is now a struct type
number.real_part = 3;
number.img_part = -1;
printf("Number: %d.%d i \n",number.real_part, number.img_part);
}
Each time I decide to use a struct type I will need this keyword 'struct 'something' 'name'.'typedef' will simply rename that type and I can use that new name in my program every time I want. So our code will be:
typedef struct complex{int real_part, img_part; }COMPLEX;
//now COMPLEX is the new name for this structure and if I want to use it without
// a keyword like in the first example 'struct complex number'.
main(){
COMPLEX number; // number is now the same type as in the first example
number.real_part = 1;
number.img)part = 5;
printf("%d %d \n", number.real_part, number.img_part);
}
If you have some local object(struct, array, valuable) that will be used in your entire program you can simply give it a name using a 'typedef'.
Turns out in C99 typedef is required. It is outdated, but a lot of tools (ala HackRank) use c99 as its pure C implementation. And typedef is required there.
I'm not saying they should change (maybe have two C options) if the requirement changed, those of us studing for interviews on the site would be SOL.
At all, in C language, struct/union/enum are macro instruction processed by the C language preprocessor (do not mistake with the preprocessor that treat "#include" and other)
so :
struct a
{
int i;
};
struct b
{
struct a;
int i;
int j;
};
struct b is expended as something like this :
struct b
{
struct a
{
int i;
};
int i;
int j;
}
and so, at compile time it evolve on stack as something like:
b:
int ai
int i
int j
that also why it's dificult to have selfreferent structs, C preprocessor round in a déclaration loop that can't terminate.
typedef are type specifier, that means only C compiler process it and it can do like he want for optimise assembler code implementation. It also dont expend member of type par stupidly like préprocessor do with structs but use more complex reference construction algorithm, so construction like :
typedef struct a A; //anticipated declaration for member declaration
typedef struct a //Implemented declaration
{
A* b; // member declaration
}A;
is permited and fully functional. This implementation give also access to compilator type conversion and remove some bugging effects when execution thread leave the application field of initialisation functions.
This mean that in C typedefs are more near as C++ class than lonely structs.