I have a sample code for a microcontroller.
There is a structure typedefd as shown below.
typedef struct _AT91S_SYS {
AT91_REG AIC_SMR[32]; // Source Mode Register
AT91_REG AIC_SVR[32]; // Source Vector Register
AT91_REG AIC_IVR; // IRQ Vector Register
...
} AT91S_SYS, *AT91PS_SYS;
I have used typedef with structs like } AT91S_SYS;.
What does this additional part does? *AT91PS_SYS; in } AT91S_SYS, *AT91PS_SYS;
Is it a pointer to the struct _AT91S_SYS type?
AT91_REG is a typedef of volatile unsigned int
This just defines the type AT91PS_SYS as a pointer to AT91S_SYS.
The easiest way to understand typedef, by the way, is to read the rest of the declaration as if it were just a variable declaration. But, instead of defining variables, you're defining types using whatever type the variable would have had.
So, for example,
int x, *y, z[5];
defines three variables, int x, int *y and int z[5].
Therefore,
typedef int x, *y, z[5];
defines two types, x == int, y == int * and z == int[5]. Simple!
Yes, you are right, the syntax is equivalent to this:
typedef struct _AT91S_SYS AT91S_SYS;
typedef struct _AT91S_SYS *AT91PS_SYS;
So AT91PS_SYS is a pointer type of AT91S_SYS.
Related
What does *B in the following code mean? I understand this mixture between typedef and struct. However, this *B is strange.
typedef struct Something
{
...
}
A, *B;
I saw multiple questions asking about mixing typedef with struct but non of them talked about this double definition.
This is a less-common use case for the typedef keyword that allows you to define two or more type aliases in a single line. Here, this says
make an alias named A that represents the struct itself, and
make an alias named B that represents a pointer to the struct.
In that sense, it's similar to writing something like
int A, *B;
Here, this declares an integer named A and a pointer to an integer named B. The syntax here involving the * works very similarly to what's going on in the typedef statement, except that instead of introducing variables it's introducing types.
Another way to see this: this is equivalent to breaking things apart into two separate statements:
typedef struct {
...
} A;
typedef A* B;
Here, the first one says "A now refers to this struct type, and B now refers to a pointer to an A."
I have seen this type of definition a lot in Microsoft code:
typedef struct {
int count;
char buffer[128];
} BUFFER, *PBUFFER;
It allows code like this to be written:
void read_buffer(PBUFFER pBuffer) {
// Do something with pBuffer
}
int main(void) {
BUFFER buffer;
read_buffer(&buffer);
return 0;
}
To directly answer your question: This kind of typedef allows a type and a pointer to a type to be defined at the same location in the code.
Having a struct -
typedef struct Point{
....
}
I want to write its prototype before the main() , something like -
typedef struct Point ;
int main() {
Point p1 ,p2 ;
...
}
typedef struct Point {
int x;
int y;
} Point;
The above gives me error - unknown type name 'Point' .
How could I achieve that right ?
Edit:
I know that it would be work if I define to struct before the main() . I just want to know whether it have any prototye similarly to function prototye.
You cannot do this, because the C language is organized around one pass compilation. At the point where a type name is used to declare or define something, that type have been previously declared.
There is a relaxation of this rule, namely: you can define incomplete types in C. However, incomplete types cannot be used to define objects: at least, not certain kinds of objects. So this is invalid:
struct foo; /* introduces incomplete type foo */
struct foo x; /* incomplete type for external definition is okay, as long
as the type is completed before the end of the translation unit. */
extern struct foo e; /* incomplete type for external declaration is allowed even if
the type is not completely known in this translation unit
at all. A definition of the object e must exist somewhere
in the linked program---unless e is not used; then a definition
need not exist at all. */
void func(void)
{
struct foo y; /* incomplete type not okay here */
}
struct bar {
struct foo z; /* not okay here */
};
struct foo {
char *s;
}; /* struct foo is now a complete type, but it's too late in the file */
The last declaration above, which completes the type struct foo allows for the struct foo x; definition to be valid. So there is some "lexically retroactive" action in the C type system; it's just not general.
The situations marked as "not okay" require the struct type to be complete at that point in the source code.
If you want to define local variables of type Point in your main function, that type must be declared and complete prior to that function. If that type is not complete, you can still define variables of type Point *: pointer to Point. But these pointers cannot be dereferenced.
This declaration:
typedef struct Point;
is not valid in C.
How could I achieve that right ?
typedef struct Point {
int x;
int y;
} Point;
int main() {
Point p1 ,p2 ;
}
You cannot achieve the same with struct Point declaration after main because the implementation has to know the storage of Point objects p1 and p2 when you declare them in main.
You won't be able to do that because the compiler would need to know how much space to allocate for Point when you allocate it. Prototyping wouldn't give you this information.
You could do this, as the size of the pointer will be known:
typedef struct Point Point;
int main() {
Point * p1;
}
struct Point {
int x;
int y;
};
I don't know if that will meet your needs, though
The problem is that you are declaring your struct after main.
typedef struct Point ; // you dont really need this.
typedef struct Point {
int x;
int y;
} Point;
int main() {
Point p1 ,p2 ;
...
}
even better is this:
typedef struct Point {
int x;
int y;
} Point;
int main() {
Point p1 ,p2 ;
...
}
Put the declaration in another file (e.g., Point.h) that gets included at the top of your main() file, and put the definition in a separately-compiled implementation file (e.g., Point.cpp).
I want to convert the libusb.h into PureBasic code and now I have this line:
typedef void (LIBUSB_CALL *libusb_transfer_cb_fn)(struct libusb_transfer *transfer);
What does this typedef do?
Later on there are lines like this:
void LIBUSB_CALL libusb_free_device_list(libusb_device **list, int unref_devices);
Thanks in advance!
LIBUSB_CALL is just a type annotation. It probably doesn't do anything.
This declares a type "f" that is a function pointer returning void and taking "params":
typedef void (*f)(params...)
libusb_transfer_cb_fn is a type representing a function pointer tacking a pointer to a libusb_transfer struct and returning nothing (void).
The syntax for typedef in C is peculiar. What you do is write an ordinary declaration:
int x, *y, z[2];
and then insert the keyword typedef in front. This tells the compiler that, for each variable declared, don't actually declare a variable; instead, make that a new name for the type that the variable would have had, if it were a variable. So:
typedef int x, *y, z[2];
makes x an alias for int, y an alias for int *, and z an alias for int [2].
If you take the typedef off the original line you get:
void (LIBUSB_CALL *libusb_transfer_cb_fn)(struct libusb_transfer *transfer);
(which is only syntactically valid if LIBUSB_CALL is a macro, probably some compiler-specific modifier like __stdcall or __fastcall), which is already a little peculiar because of C's need to parenthesize pointers-to-functions. But it would declare (and define) libusb_transfer_cb_fn as a variable of type "pointer to function taking one argument (the transfer thing) and returning void. So the typedef makes libusb_transfer_cb_fn an alias for that type.
The name obviously (well... :-) ) means: "callback function for libusb after a transfer operation".
The idea would be that a later bit of C code might read something like:
extern libusb_transfer_cb_fn abc_func;
which tells you that there's some global variable abc_func of type "pointer to libusb callback", or:
some_return_type xyz_func(libusb_transfer_cb_fn funcp, int a, char *b) {
struct libusb_transfer x;
... some code that fills in x ...
(*funcp)(&x);
}
typedef int (*P)(char *(*)());
int (*P)(char *(*)());
Both seems to be doing the same thing to me,what's the typedef there for?
The first declares a type called P that you can use in the declaration of other variables. The second declares a variable of that same type.
For illustrative purposes:
typedef int (*P)(char *(*)());
int main() {
int (*Q)(char *(*)());
P R;
}
In this example the variables Q and R have exactly the same type.
The typedef defines P to be a function pointer type. The second version defines P to be a function pointer.
A type can be used to declare variables. After
typedef int (*P)(char *(*)());
you can use
P p;
which will be equivalent to
int (*p)(char *(*)());
The simple answer would be you are creating a new datatype through typedef.
Let's take a simple example, in embedded system we use only unsigned numbers.
Now 1 way is I write
unsigned int xyz;
So here I would have to type unsigned everywhere.. What if I forget to type unsigned somewhere, it's very difficult to figure out that if the code is released. So simple way would be
typedef unsigned int uint;
So now you can use uint as a datatype. So whenever parser encounter uint, it would read it as unsigned int.
So in your case you can use P as a datatype in code. So Like in the first example
P xyz ;
would be parsed as
int (*xyz)(char *(*)());
What is the use of typedef keyword in C ?
When is it needed?
typedef is for defining something as a type. For instance:
typedef struct {
int a;
int b;
} THINGY;
...defines THINGY as the given struct. That way, you can use it like this:
THINGY t;
...rather than:
struct _THINGY_STRUCT {
int a;
int b;
};
struct _THINGY_STRUCT t;
...which is a bit more verbose. typedefs can make some things dramatically clearer, specially pointers to functions.
From wikipedia:
typedef is a keyword in the C and C++ programming languages. The purpose of typedef is to assign alternative names to existing types, most often those whose standard declaration is cumbersome, potentially confusing, or likely to vary from one implementation to another.
And:
K&R states that there are two reasons for using a typedef. First, it provides a means to make a program more portable. Instead of having to change a type everywhere it appears throughout the program's source files, only a single typedef statement needs to be changed. Second, a typedef can make a complex declaration easier to understand.
And an argument against:
He (Greg K.H.) argues that this practice not only unnecessarily obfuscates code, it can also cause programmers to accidentally misuse large structures thinking them to be simple types.
Typedef is used to create aliases to existing types. It's a bit of a misnomer: typedef does not define new types as the new types are interchangeable with the underlying type. Typedefs are often used for clarity and portability in interface definitions when the underlying type is subject to change or is not of importance.
For example:
// Possibly useful in POSIX:
typedef int filedescriptor_t;
// Define a struct foo and then give it a typedef...
struct foo { int i; };
typedef struct foo foo_t;
// ...or just define everything in one go.
typedef struct bar { int i; } bar_t;
// Typedef is very, very useful with function pointers:
typedef int (*CompareFunction)(char const *, char const *);
CompareFunction c = strcmp;
Typedef can also be used to give names to unnamed types. In such cases, the typedef will be the only name for said type:
typedef struct { int i; } data_t;
typedef enum { YES, NO, FILE_NOT_FOUND } return_code_t;
Naming conventions differ. Usually it's recommended to use a trailing_underscore_and_t or CamelCase.
Explaining the use of typedef in the following example. Further, Typedef is used to make the code more readable.
#include <stdio.h>
#include <math.h>
/*
To define a new type name with typedef, follow these steps:
1. Write the statement as if a variable of the desired type were being declared.
2. Where the name of the declared variable would normally appear, substitute the new type name.
3. In front of everything, place the keyword typedef.
*/
// typedef a primitive data type
typedef double distance;
// typedef struct
typedef struct{
int x;
int y;
} point;
//typedef an array
typedef point points[100];
points ps = {0}; // ps is an array of 100 point
// typedef a function
typedef distance (*distanceFun_p)(point,point) ; // TYPE_DEF distanceFun_p TO BE int (*distanceFun_p)(point,point)
// prototype a function
distance findDistance(point, point);
int main(int argc, char const *argv[])
{
// delcare a function pointer
distanceFun_p func_p;
// initialize the function pointer with a function address
func_p = findDistance;
// initialize two point variables
point p1 = {0,0} , p2 = {1,1};
// call the function through the pointer
distance d = func_p(p1,p2);
printf("the distance is %f\n", d );
return 0;
}
distance findDistance(point p1, point p2)
{
distance xdiff = p1.x - p2.x;
distance ydiff = p1.y - p2.y;
return sqrt( (xdiff * xdiff) + (ydiff * ydiff) );
} In front of everything, place the keyword typedef.
*/
typedef doesnot introduce a new type but it just provide a new name for a type.
TYPEDEF CAN BE USED FOR:
Types that combine arrays,structs,pointers or functions.
To facilitate the portability , typedef the type you require .Then when you port the code to different platforms,select the right type by making changes only in the typedef.
A typedef can provide a simple name for a complicated type cast.
typedef can also be used to give names to unnamed types. In such cases, the typedef will be the only name for said type.
NOTE:-SHOULDNT USE TYPEDEF WITH STRUCTS. ALWAYS USE A TAG IN A STRUCTURE DEFINITION EVEN IF ITS NOT NEEDED.
from Wikipedia:
"K&R states that there are two reasons for using a typedef. First ... . Second, a typedef can make a complex declaration easier to understand."
Here is an example of the second reason for using typedef, simplifying complex types (the complex type is taken from K&R "The C programming language second edition p. 136).
char (*(*x())[])()
x is a function returning pointer to array[] of pointer to function returning char.
We can make the above declaration understandable using typedefs. Please see the example below.
typedef char (*pfType)(); // pf is the type of pointer to function returning
// char
typedef pfType pArrType[2]; // pArr is the type of array of pointers to
// functions returning char
char charf()
{ return('b');
}
pArrType pArr={charf,charf};
pfType *FinalF() // f is a function returning pointer to array of
// pointer to function returning char
{
return(pArr);
}
It can alias another type.
typedef unsigned int uint; /* uint is now an alias for "unsigned int" */
typedef unsigned char BYTE;
After this type definition, the identifier BYTE can be used as an abbreviation for the type unsigned char, for example..
BYTE b1, b2;