Reputation: 177
I came across the code and it was kind of strange to me I am unable to understand what it means.
typedef struct alpha *Abc;
this is where Abc is defined;
struct alpha{
Abc s;//what does this mean
}
also some where in function it is used like this
Abc iAmFunc(Abc beta,int a){
some thing is performed
return variable of type Abc
}
I dont understand the purpose of doing this can anyone explain me!!
Upvotes: 1
Views: 1998
Reputation: 123448
I want to expand on this part of Klutt's excellent answer a bit:
Be restrictive with typedefs. Often they just clutters the code and makes it harder to follow. Use them when they fill a purpose. Be especially restrictive with aliasing pointers. I only use them for function pointers and completely opaque objects.
What Klutt is talking about here is abstraction - hiding implementation details of a type from the person using it. Think about the FILE
type in the standard library (stdio.h
) - it is almost always a typedef
name for a reasonably complex struct
type.
However, the standard library doesn't just create the typedef
name, it also provides a set of functions to create and manipulate FILE
objects for you. You never manipulate the contents of a FILE
object directly, you always use the stdio
functions to interact with it. The abstraction is complete in that you can do everything necessary with a FILE
without having to know any details of its implementation.
Contrast that with something like
typedef struct coord { double lat, lon; } Coordinates;
Coordinates c;
c.lat = 20.0;
c.lon = 47.5;
...
printf( "Coordinates: {%f:%f}\n", c.lat, c.lon );
where all I've done is create the typedef name Coordinates
. In order to use an object of Coordinates
type, you have to know that it's a struct
type with two members of type double
named lat
and lon
. The abstraction is "leaky" - details of the implementation "leak" out to the programmer.
To create a proper abstraction, I would need to expose only the typedef name without exposing its implementation, and I would need to provide a set of functions to manipulate coordinate types:
// Coord.h
/**
* Forward declare the struct type; the type is incomplete at this point,
* and will be completed in Coord.c
*/
struct coord;
/**
* Create the typedef name - you can create typedef names for (and pointers
* to) incomplete types.
*/
typedef struct coord Coordinates;
/**
* Create a new Coordinates object and return a pointer to it. Since the
* Coordinates type is *incomplete* at this point, we cannot declare an
* object of that type nor a function that returns an object of that type.
* We can only declare things that are *pointers* to that type.
*/
Coordinates *newCoord( double, double );
/**
* Set the coordinates on an existing Coordinates object
*/
setCoord( Coordinates *, double, double );
/**
* Compute the bearing from one set of coordinates to the other
*/
double bearing( const Coordinates *, const Coordinates * );
/**
* Return a string representation of the coordinate pair (suitable for
* passing to printf and other display functions)
*/
char *format( const Coordinates * );
etc., etc., etc.
This is why both Klutt and I recommend that you not use typedef
just to rename things or avoid using the struct
keyword. Use it as part of creating a complete abstraction, or don't use it at all.
Also, DO NOT HIDE POINTERS BEHIND typedef
s!!! It is a practice that will bite you in the ass at some point. Pointer semantics are special and should not be hidden.
Upvotes: 1
Reputation: 11317
typedef
is used to give something a new name. For example typedef int ID
.
This makes a new type alias for int with the name ID, allowing you to use it. For example:
struct S
{
ID id;
};
This is especially useful to make your code more readable, as having 4 ints in a class/struct ain't self explanatory.
In modern C++, we tend to step away from typedef
and use using
instead.
For example: using ID = int;
this removes confusion when reading as it's obvious which is the new name and which the old. Though, it improves even more for pointers, like: using IntPtr = int *;
iso typedef int *IntPtr;
or function pointers: using IntIntFunc = int(*)(int);
iso typedef int(*IntIntFunc)(int);
In C++, you can even take this a step further, and use it to make new strong types, see Strong types for strong interfaces - fluentcpp.com for the details. (Also works with typedef)
The short version:
using ID = NamedType<int, struct IDTag>;
ID id = ID{0}; // OK
int width = 5;
id = width; // Compilation error
id = ID{width}; // OK again
This can prevent bugs because of typos where you accidentally mix types. A more useful place where this could make sense:
struct Rectangle { Height h; Width w; };
Rectangle r{5, 3}; // Doesn't compile
Rectangle r{Width{5}, Height{3}}; // Doesn't compile
Rectangle r{Height{3}, Width{5}}; // Does compile
Upvotes: 0
Reputation: 31296
Note, this is for C and not C++. Maybe it's applicable for C++ too, but I don't know.
typedef a b
makes b
an alias for a
What typedef struct alpha *Abc;
is to make Abc
an alias for struct alpha *
. After you have created this, these two are equivalent:
struct alpha *ptr;
Abc ptr;
There are a few different uses for this:
It reduces how much you need to write. You can skip the struct
word for instance. Many would say that this is NOT a good reason to use typedef.
It can give a more descriptive name for certain things. Examples:
typedef char* string; // I would never use this. It's just an example.
typedef int[3] vector; // However, this is something I would consider.
It can make it easier to change the type for a large code base in certain situations. Suppose you have this code:
int16_t foo(int16_t a)
{
int16_t b = a+1;
for(int16_t = 0; i<b; i++) {
...
And later you realize that it would be a good idea to change to int32_t
instead. If the code instead looked like this, you would only need to change one line:
typedef int16_t T
T foo(T a)
{
T b = a+1;
for(T = 0; i<b; i++) {
...
Be restrictive with typedefs. Often they just clutters the code and makes it harder to follow. Use them when they fill a purpose. Be especially restrictive with aliasing pointers. I only use them for function pointers and completely opaque objects. Same thing with structs and unions. IMHO, 99% of the typedefs I see in questions here at SO are not necessary and seems to be there just because people think that they should.
If you consider typedefing a struct, ask yourself if it would be good to anyone reading the code to know that a declaration is a struct. If yes, declare it with the struct
keyword. Of course you could invent something like typedef struct my_struct my_struct_s
but is it really worth the effort? I'd say no.
It can be worth noting that C has something that seems like a simple form of namespace. This means that this completely valid:
typedef struct mystruct mystruct;
struct mystruct a;
mystruct b;
So mystruct
is an alias for mystruct
. And this is what you should do, unless you have a good reason not to.
I once wrote a related answer and if that answer wasn't so heavily focused on just structs, I would have made this question a duplicate.
In comments below, I saw this example:
typedef unsigned short int int_16;
and this is a HORRIBLE example. First, int_16
gives the impression that it is a signed type, which it is clearly not. Secondly, short int
(and its unsigned counterpart) is guaranteed to have at least 16 bits, but int_16
gives the impression that it have exactly 16 bits. Depending on what you want, there are a few good ones in the standard:
int16_t
and uint16_t
- Exactly 16 bitsint_least16_t
and uint_least16_t
- At least 16 bitsint_fast16_t
and uint_fast16_t
- At least 16 bits, but hint to the compiler that you want the fastest typeUpvotes: 1
Reputation: 2395
The typedef defines a pointer type to struct alpha
with type name Abc
. Because of this, Abc s;
translates to struct alpha *s;
Upvotes: 3