Related
I wonder if typedef and #define are the same in c?
typedef obeys scoping rules just like variables, whereas define stays valid until the end of the compilation unit (or until a matching undef).
Also, some things can be done with typedef that cannot be done with define.
For example:
typedef int* int_p1;
int_p1 a, b, c; // a, b, c are all int pointers
#define int_p2 int*
int_p2 a, b, c; // only the first is a pointer, because int_p2
// is replaced with int*, producing: int* a, b, c
// which should be read as: int *a, b, c
typedef int a10[10];
a10 a, b, c; // create three 10-int arrays
typedef int (*func_p) (int);
func_p fp; // func_p is a pointer to a function that
// takes an int and returns an int
No.
#define is a preprocessor token: the compiler itself will never see it.
typedef is a compiler token: the preprocessor does not care about it.
You can use one or the other to achieve the same effect, but it's better to use the proper one for your needs
#define MY_TYPE int
typedef int My_Type;
When things get "hairy", using the proper tool makes it right
#define FX_TYPE void (*)(int)
typedef void (*stdfx)(int);
void fx_typ(stdfx fx); /* ok */
void fx_def(FX_TYPE fx); /* error */
No, they are not the same. For example:
#define INTPTR int*
...
INTPTR a, b;
After preprocessing, that line expands to
int* a, b;
Hopefully you see the problem; only a will have the type int *; b will be declared a plain int (because the * is associated with the declarator, not the type specifier).
Contrast that with
typedef int *INTPTR;
...
INTPTR a, b;
In this case, both a and b will have type int *.
There are whole classes of typedefs that cannot be emulated with a preprocessor macro, such as pointers to functions or arrays:
typedef int (*CALLBACK)(void);
typedef int *(*(*OBNOXIOUSFUNC)(void))[20];
...
CALLBACK aCallbackFunc; // aCallbackFunc is a pointer to a function
// returning int
OBNOXIOUSFUNC anObnoxiousFunc; // anObnoxiousFunc is a pointer to a function
// returning a pointer to a 20-element array
// of pointers to int
Try doing that with a preprocessor macro.
#define defines macros.
typedef defines types.
Now saying that, here are a few differences:
With #define you can define constants that can be used in compile time. The constants can be used with #ifdef to check how the code is compiled, and specialize certain code according to compile parameters.
You can also use #define to declare miniature find-and-replace Macro functions.
typedef can be used to give aliases to types (which you could probably do with #define as well), but it's safer because of the find-and-replace nature of #define constants.
Besides that, you can use forward declaration with typedef which allows you to declare a type that will be used, but isn't yet linked to the file you're writing in.
Preprocessor macros ("#define's") are a lexical replacement tool a la "search and replace". They are entirely agnostic of the programming language and have no understanding what you're trying to do. You can think of them as a glorified copy/paste mechanic -- occasionally that's useful, but you should use it with care.
Typedefs are a C language feature that lets you create aliases for types. This is extremely useful to make complicated compound types (like structs and function pointers) readable and handlable (in C++ there are even situations where you must typedef a type).
For (3): You should always prefer language features over preprocessor macros when that's possible! So always use typedefs for types, and constant values for constants. That way, the compiler can actually interact with you meaningfully. Remember that the compiler is your friend, so you should tell it as much as possible. Preprocessor macros do the exact opposite by hiding your semantics from the compiler.
They are very different, although they are often used to implement custom data types (which is what I am assuming this question is all about).
As pmg mentioned, #define is handled by the pre-processor (like a cut-and-paste operation) before the compiler sees the code, and typedef is interpreted by the compiler.
One of the main differences (at least when it comes to defining data types) is that typedef allows for more specific type checking. For example,
#define defType int
typedef int tdType
defType x;
tdType y;
Here, the compiler sees variable x as an int, but variable y as a data type called 'tdType' that happens to be the same size as an int. If you wrote a function that took a parameter of type defType, the caller could pass a normal int and the compiler wouldn't know the difference. If the function instead took a parameter of type tdType, the compiler would ensure that a variable of the proper type was used during function calls.
Also, some debuggers have the ability to handle typedefs, which can be much more useful than having all custom types listed as their underlying primitive types (as it would be if #define was used instead).
No. typedef is a C keyword that creates an alias for a type. #define is a pre-processor instruction, that creates a text replacement event prior to compilation. When the compiler gets to the code, the original "#defined" word is no longer there. #define is mostly used for macros and global constants.
AFAIK, No.
typedef helps you set up an "alias" to an existing data type. For eg. typedef char chr;
#define is a preprocessor directive used to define macros or general pattern substitutions. For eg. #define MAX 100, substitutes all occurrences of MAX with 100
As mentioned above, there is a key difference between #define and typedef. The right way to think about that is to view a typedef as being a complete "encapsulated" type. It means that you cannot add to it after you have declared it.
You can extend a macro typename with other type specifiers, but not a typedef'd typename:
#define fruit int
unsigned fruit i; // works fine
typedef int fruit;
unsigned fruit i; // illegal
Also, a typedef'd name provides the type for every declator in a declaration.
#define fruit int *
fruit apple, banana;
After macro expansion, the second line becomes:
int *apple, banana;
Apple is a pointer to an int, while banana is an int. In comparison. a typedef like this:
typedef char *fruit;
fruit apple, banana;
declares both apple and banana to be the same. The name on the front is different, but they are both pointers to a char.
Another reason to use typedef (which has only been mentioned briefly in other answers and yet I think is the entire reason typedef was created) is to make debugging easier when using libraries that have custom types. For example, I'll use a type-conversion error. Both the codes below will print a compile-time error saying that a char is not comparable to a string, but in different ways.
typedef char letter;
letter el = 'e';
if(el == "hello");
The above code will print something like the variable "el" of type letter (aka "char") is not compatable with type "char*"
#define letter char
letter el = 'e';
if(el == "hello");
This code will instead print the variable "el" of type char is not compatable with type "char*"
This may seem silly because I'm defining "letter" as "char", but in more complex libraries this can be extremely confusing because pointers to objects like buttons, windows, sound servers, images, and lots of other things are defined as unsigned char *, which would only be debuggable as exactly that when using the #define method.
As everyone said above, they aren't the same. Most of the answers indicate typedef to be more advantageous than #define.
But let me put a plus point of #define :when your code is extremely big, scattered across many files, it's better to use #define; it helps in readability - you can simply preprocess all the code to see the actual type definition of a variable at the place of its declaration itself.
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 ran into this problem debugging an AVR microcontroller:
I have a main.c file with numerous variable definitions, amongst them an array of structs, like this:
struct mystruct mystruct_array[COUNT];
In another .c file I refer to this array as external, but I left away the array brackets and size so I wouldn't repeat myself and just declared the variable as a pointer (because arrays are essentially pointers, aren't they?):
extern struct mystruct *mystruct_array;
But when I checked the address of the array using printf("%p\n", mystruct_array);I got a null pointer instead of the array's location in memory. Also if I would access the subsequent items in the array, like printf("%p\n", &(mystruct_array[n])); it would print address 0 plus n times sizeof(struct mystruct).
Only after I changed the definition to
extern struct mystruct mystruct_array[COUNT];
(exactly the same as in main.c), I got the true address of the array.
My question: Why does this make a difference to the compiler (in my case avr-gcc)?
That's a fun one.
When you write :
struct mystruct mystruct_array[COUNT];
You create a global array of mystruct structs, there are COUNT of them, and since you didn't initialize it, it'll be filled with zeros.
When you then write:
extern struct mystruct *mystruct_array;
You tell the compiler that there's a variable called mystruct_array somewhere and that it's a pointer. But it's not, it's an array. So the compiler is going to read the content of the array as if it were a pointer.
So when you try to output the value of that pointer, the compiler goes fetch mystruct_array in memory and outputs its content as if it were a pointer. Since it's actually an array full of zeros, you're seeing a null pointer in the output.
Instead you should write something like:
extern struct mystruct mystruct_array[];
So the compiler knows the correct type of your variable. You can specify the length in the square brackets here, but you don't have to.
I'd recommend you go read up on the differences between pointers and arrays to make sure you don't confuse them in the future.
The ideal way to do this is to put an extern declaration in a header file, and a definition in exactly one file. For example,
header.h
extern struct mystruct mystruct_array[];
/* or extern struct mystruct mystruct_array[COUNT] */
main.c
#include "header.h"
#define COUNT 10
/* should have an initializer to be a definition: */
struct mystruct mystruct_array[COUNT] = { 0 };
/* ... */
other.c
#include "header.h"
/* ... */
printf("%p\n", mystruct_array);
That saves you repetition, and limits the places where you might need to make changes. Note that if your header does not define the number of elements in the array, then you cannot apply the sizeof operation to that array in files other than the one that also provides the array definition.
Note, too, that although arrays are not pointers, in most contexts in C source code, an array name is converted to a pointer to the first element of the array. This is the source of the misapprehension that arrays are pointers. Although they are not pointers, in many ways they act as if they were.
The declaration of extern means that the declared object is global in an other C file. Then, when you generate the object file, it is generated also if the declared object (in this case the structure) is not present.
If you declare:
extern struct structname * s;
means that in the other C module there's a global visible pointer to a structure structname s.
If you declare:
extern struct structname s;
means that in the other C module there's a global visible structure structname s!
When you will link the program, if you don't indicate to the linker to link the object that contains the structure, you will get an Undefined reference!
I'm having problems understanding the syntax of a pointer to a function using typedef. I've read a lot of answers but still couldn't understand something.
I'll try to explain how I see things so you could understand my thinking.
So we use typedef to give aliases to existing types for example :
typedef int number;
Will make it so we could use a number same as an integer (similar to preprocessor directives - I know there're some differences like when making a typedef of a pointer).
Another example :
typedef struct
{
int num;
} MyStruct;
Will give the unnamed structure an alias named MyStruct.
So Here's the syntax of a pointer to function typedef:
typedef int (*pFunc)(int, int);
Maybe I'm having hard time to understand this since typedef is like it's name giving aliases to TYPES and a function is not exactly type but anyway, from my understanding this is more of a pointer to some sort of a function signature, so the first int is the returned type, the second parenthesis are to indicate what types are the arguments being passed to the function.
Now what I don't quite understand is this part :
(*pFunc)
What I think it is, is that we create a new type (using typedef)
named pFunc that is a pointer and that's the role of the *. Now we
could create variables of this type that will point to ANY function
with the signature we described. Am I correct ?
Ok, say I'm correct, usually pointers to some memory are declared as follow :
int *p;
double *p;
.
.
.
So wouldn't it make more sense to do it as follow :
(pFunc*)
Because to me it looks like if the asterisk is before the name it looks like pFunc is a variable name of type pointer of some type and not an actual type pointer.
Can we do that ^ ? If so, is it commonly used to put the asterisk
after and not before ? If it's more common to put it before then why
is that ? Because like I said when we define a pointer type we always
put the asterisk after the name itself like the examples above so why
is that exactly ?
Another question regarding to this, I don't quite understand what are
the job of the parenthesis around *pFunc.
I think that they're used to indicate that pFunc type pointer of something and if we wouldn't do put parenthesis then the return type
of the signature will be of type int* instead of just int, am I
correct here ?
Ok, another thing that bothers me about it as the order of the syntax.
So far, in all typedef definitions we had the type on the left and the alias(es) on the right.
typedef int number;
typedef struct
{
int num;
} MyStruct;
We see that the int and the struct are the types which are being on the left and the alias we gave them are on the right.
Now, in pointers to function typedef it doesn't follow this convention.
We have the type returned of the function on the right then the typename in parenthesis then the type of the arguments in parenthesis, this order makes me confused after looking on how the other typedef are working on the same order.
Wouldn't it make more sens to do something like this ? :
typedef int (int,int) Func; So we have a typedef first, the type we want to give alias(es) to, which in this case is a function
signature which takes 2 ints and return an int, and then on the right
we have the alias name. Won't it make more sense ? this follows the
other typedef order, I just don't get the function pointer order that
much ..
Another question of mine : When we make a pointer to a function, what
does it actually mean ? I understand we can call this function using
our alias but pointers like variables are stored in a memory address
? What is there to store for a function ?
Lastly, I've read that the keyword extern has something to do with
pointers to function but couldn't understand what this keyword does,
could someone explain to me what it does ?
The typedef uses the same syntax for declaring types as would normally be used for declaring values.
For instance, if we declare an int called myInt, we do:
int myInt;
If we want to declare a type called myIntType to be an int, we simply add typedef:
typedef int myIntType;
We can declare a function myFunc, as follows:
int myFunc(int a, int b);
Which tells the compiler that there is an actual function with that name and signature that we can call.
We can also declare a function type myFuncType by doing:
typedef int myFuncType(int a, int b);
And we could do:
myFuncType myFunc;
Which is equivalent to the previous declaration of myFunc (although this form would rarely be used).
A function is not a conventional value; it represents a block of code with an entry point address. Function declarations like those above are implicitly extern; they tell the compiler that the named thing exists somewhere else. However, you can take the address of a function, which is called a function pointer. A function pointer can point to any function with the correct signature. A pointer is declared by prefixing the name of the type/value with a *, so, we might try:
int *myFuncPtr(int a, int b);
But this would be incorrect because the * binds more tightly with the int, so we have declared that myFuncPtr is a function that returns a pointer to an int. We must put parens around the pointer and name to change the binding order:
int (*myFuncPtr)(int a, int b);
And to declare a type, we simply add typedef to the front:
typedef int (*myFuncPtrType)(int a, int b);
In the declaration of myInt above, the compiler allocated some memory for the variable. However, if we were writing some code in a different compilation unit, and wanted to reference myInt, we would need to declare it as extern (in the referencing compilation unit) so that we reference the same memory. Without the extern, the compiler would allocate a second myInt, which would result in a linker error (actually that's not quite true because C allows tentative definitions, which you shouldn't use).
As noted above, functions are not normal values, and are always implicitly extern. However, function pointers are normal values, and need the extern if you are trying to reference a global function pointer from a separate compilation unit.
Normally, you would put externs for your global variables (and functions) into a header file. You would then include the header into the compilation units that contain the definitions of those variables and functions so that the compiler can make sure the types match.
The syntax for a variable definition or declaration is the type followed by one or more variables possibly with modifiers. Some simple examples would be:
int a, b; // two int variables a and b
int *a, b; // pointer to an int variable a and an int variable b
int a, *b, **c; // int variable a, pointer to an int variable b, and pointer to a pointer to an int variable c
Notice that in all of these the asterisk modifies the variable to the right of the asterisk, changing it from an int into a pointer to an int or a pointer to a pointer to an int. The variables defined might be used like:
int a, *b, **c, d;
a = 5; // set a == 5
b = &a; // set b == address of a
c = &b; // set c == address of b which in this case has the address of int variable a
d = **c; // put value of a into d using pointer to point to an int variable a
d = *b; // put value of a into d using pointer to an int variable a
d = a; // put value of a into d using the variable a directly
The extern statement
The extern statement is used to indicate that the definition of a variable is located in some other file and that the variable has global visibility. So you can declare a variable using the extern keyword to be explicit about a variable so that the C compiler will have the information it needs to do a good level of checking when compiling. The extern indicates that the variable is actually defined with its memory allocation somewhere other than the file where the source using the variable is located.
Using typedef
The typedef is a very nice feature of modern C because it allows you to create an alias that amounts to a kind of halfway new type. To have the full capability of creating a new type really requires the class type features of C++ which allows the definition of operators for the new type as well. However typedef does provide a good way of allowing a programmer to create an alias for a type.
Most uses of typedef are to provide a way to make it shorter and cleaner to write a variable definition. It is used a lot with struct definitions for that reason. So you might have a struct definition like the following:
typdef struct {
int iA;
int iB;
} MyStruct, *PMyStruct;
This will create two new aliases for the struct, one for the struct itself and one for a pointer to the struct and these might be used like:
MyStruct exampleStruct;
PMyStruct pExampleStrut;
pExampleStruct = &exampleStruct;
This example has the basic structure of typedef keyword, definition of the new type in terms of existing types, and name of the new type.
Old style C before typedef
Years ago in the older C compiler days before typedef was added to the C standard, people would often use the C Preprocessor to define macros to create an alias for a complex type. typedef is a much cleaner way of doing it!
Before typedef was added to the C standard, you would specify a tag for the struct and the result would be code that looked like this:
struct myTagStruct { // create a struct declaration with the tag of myTagStruct
int a;
int b;
};
struct myTagStruct myStruct; // create a variable myStruct of the struct
At which pointer people would usually add a C Preprocessor define to make it easier to write as in:
#define MYTAGSTRUCT struct myTagStruct
and then use it something like:
MYTAGSTRUCT myStruct;
However there is one major difference between using the preferred typedef syntax rather than the Preprocessor define approach. The Preprocessor works with the text of the C source code file to generate a modified version of the C source which is then compiled by the C compiler. The typedef keyword is part of the C source compiled by the C compiler so the C compiler knows about the type alias defined.
To show the difference, see the following source code.
#define PMYSTRUCT MyStruct *
typedef struct {
int a1;
int b1;
} MyStruct, *PMyStruct;
MyStruct sA, sB; //
PMyStruct psA, psB; // compiler sees this as MyStruct *psA, *psB;
PMYSTRUCT psxA, psxB; // Preprocessor generates MyStruct * psxA, psxB;
psA = &sA;
psB = &sB;
psxA = &sA;
psxB = &sB; // compiler error - psxB is not a pointer variable
Using typedef with function pointers
The syntax of typedef for function pointers is a bit unusual. It looks somewhat like a function declaration but does have a slight twist with an additional pointer syntax.
typedef int (*pFunc)(int a1, int b1);
This says the following:
create a typedef for a variable type pFunc
a variable defined as a pFunc type is a pointer
what the variable points to is a function with two int arguments that returns an int
The parenthesizes are important because they force the compiler to interpret the source text in a way different from the default rules. The C compiler has rules that it uses to parse the source text and you can change the way that the C compiler interprets the source text by using parenthesizes. The rules have to do with the parsing and how the C compiler locates the variable name and then determines the type of the variable by using rules about left and right associativity.
a = 5 * b + 1; // 5 times b then add 1
a = 5 * (b + 1); // 5 times the sum of b and 1
int *pFunc(int a1, int b1); // function prototype for function pFunc which returns a pointer to an int
int **pFunct(int a1, int b1); // function prototype for function pFunc which returns a pointer to a pointer to an int
int (*pfunc)(int a1, int b1); // function pointer variable for pointer to a function which returns an int
int *(*pFunc)(int a1, int b1); // function pointer variable for pointer to a function which returns a pointer to an int
A function prototype is not a function pointer variable. The syntax of a typedef is similar to the syntax for a variable definition that is not using a typedef.
typedef int * pInt; // create typedef for pointer to an int
int *a; // create a variable that is a pointer to an int
pInt b; // create a variable that is a pointer to an int
typedef int (*pIntFunc)(int a1, int b1); // create typedef for pointer to a function
typedef int *pFuncWhat(int a1, int b1); // create a typedef for a function that returns a pointer to an int. seems to be legal but useful? doubt it.
int (*pFuncA)(int a1, int b1); // create a variable pFuncA that is a pointer to a function
int *FuncDecl(int a1, int b1); // declare a function that returns a pointer to an int
pIntFunc pFuncB; // create a variable pFuncB that is a pointer to a function
So what does it mean to have a pointer to a function? A function entry point has an address because a function is machine code that is located at a particular memory area. The address of the function is where the execution of the functions machine code is supposed to start.
When the C source code is compiled, a function call is translated into a series of machine instructions which jump to the address of the function. The actual machine instructions are not really a jump but are instead a call instruction which saves the return address before it makes the jump so that when the called function completes it can do a return back to where it was called from.
A function pointer variable is used like a function statement. The difference between the two is similar to the difference between an array variable and a pointer variable. An array variable is treated like a constant pointer to a variable by most C compilers. A function name is treated like a constant pointer to a function by most C compilers.
Using a function pointer
What a function pointer does give you though is flexibility though it is flexibility that as with any great power can also lead to great ruin.
One use of function pointer variables is to pass a function address as an argument to another function. For instance the C Standard library has a couple of sort functions that require an argument of a collation function for comparing two elements being sorted. Another example would be a threading library that when you create a thread, you specify the address of the function to be executed as a thread.
Since a function pointer is a variable then if you have a function pointer that needs global visibility when you declare the variable for files other than the source file where it is actually defined and its memory allocated you would use the extern keyword as part of the function pointer variable declaration. However if it is a variable that is allocated on the stack within a function or if it is used within a struct to create a member of the struct then you would not use the extern modifier on the variable.
file1.c
// define a function that we are going to make available
// through a function pointer. a function will have global
// visibility unless we use the static keyword to reduce the
// visibility to this source file.
static int myfunc(int a, float b)
{
return (a + (int) (b * 100.0));
}
// define a function pointer that contains the address of the
// function above that we are exporting from this file.
// this function pointer variable automatically has global visibility
// due to where the statement is located in the source file.
int(*pmyfunc)(int, float) = myfunc;
file1.h
// declare the function pointer, which has global visibility
// due to where it was defined in the source file. we declare
// the function pointer in an extern in order to make the
// function prototype with argument types available to the compiler
// when using this variable in other source files.
extern int(*pmyfunc)(int, float);
file 2.c
#include "file1.h"
int iifunc (int a, int b)
{
return (a + b/10 + 5);
}
// define a function that has as an argument a function pointer
// variable. this allows the caller to inject into the processing
// of this function a function to be used in the function.
int jjfunc (int a, int (*pf)(int, float))
{
return ((a / 10) + pf(a, 2000.0));
}
int kkfunc (int a, char *pName)
{
// an example of a local definition of a function pointer.
// we could have used pmyfunc directly.
int(*plocalfunc)(int, float) = pmyfunc;
// following two statements show difference between calling a
// function with a function pointer argument and calling a
// function with a function call in the argument list.
int k = jjfunc(a, plocalfunc);
int l = iifunc(a, pmyfunc(a, 3000.0));
printf ("%s - %d\n", pName, k);
return k;
}
Another case is to provide some kind of interface that hides implementation details. Let's say that you have a print function that you want to use for several different output sinks or places where the output to go, say a file, a printer, and a terminal window. This is similar in nature to how virtual functions are implemented by C++ compilers or how COM objects are implemented through a COM interface. So you could do something like the following which is a very simple example missing details:
typedef struct {
int (*pOpenSink) (void);
int (*pPrintLine) (char *aszLine);
int (*pCloseSink) (void);
} DeviceOpsStruct;
DeviceOpsStruct DeviceOps [] = {
{PrinterOpen, PrinterLine, PrinterClose},
{FileOpen, FileLine, FileClose},
{TermOpen, TermLine, TermClose}
};
int OpenDevice (int iDev)
{
return DeviceOps[iDev].pOpenSink();
}
int LineDevice (int iDev, char *aszLine)
{
return DeviceOps[iDev].pPrintLine (aszLine);
}
int CloseDevice (int iDev)
{
return DeviceOps[iDev].pCloseSink();
}
Just to make clear the explanation given by others, in C/C++, the parenthesis are right associative, therefore the following declaration:
typedef int *pFunc(int, int);
is equivalent to:
typedef int *(pFunc(int, int));
which would be the declaration prototype of a function returning a pointer to an integer and not the declaration of a pointer to a function returning an integer.
This is why you need to write the parenthesis around (*pFunc) to break the right association and tell the compiler that pFunc is a pointer to a function and not simply a function.
I wonder if typedef and #define are the same in c?
typedef obeys scoping rules just like variables, whereas define stays valid until the end of the compilation unit (or until a matching undef).
Also, some things can be done with typedef that cannot be done with define.
For example:
typedef int* int_p1;
int_p1 a, b, c; // a, b, c are all int pointers
#define int_p2 int*
int_p2 a, b, c; // only the first is a pointer, because int_p2
// is replaced with int*, producing: int* a, b, c
// which should be read as: int *a, b, c
typedef int a10[10];
a10 a, b, c; // create three 10-int arrays
typedef int (*func_p) (int);
func_p fp; // func_p is a pointer to a function that
// takes an int and returns an int
No.
#define is a preprocessor token: the compiler itself will never see it.
typedef is a compiler token: the preprocessor does not care about it.
You can use one or the other to achieve the same effect, but it's better to use the proper one for your needs
#define MY_TYPE int
typedef int My_Type;
When things get "hairy", using the proper tool makes it right
#define FX_TYPE void (*)(int)
typedef void (*stdfx)(int);
void fx_typ(stdfx fx); /* ok */
void fx_def(FX_TYPE fx); /* error */
No, they are not the same. For example:
#define INTPTR int*
...
INTPTR a, b;
After preprocessing, that line expands to
int* a, b;
Hopefully you see the problem; only a will have the type int *; b will be declared a plain int (because the * is associated with the declarator, not the type specifier).
Contrast that with
typedef int *INTPTR;
...
INTPTR a, b;
In this case, both a and b will have type int *.
There are whole classes of typedefs that cannot be emulated with a preprocessor macro, such as pointers to functions or arrays:
typedef int (*CALLBACK)(void);
typedef int *(*(*OBNOXIOUSFUNC)(void))[20];
...
CALLBACK aCallbackFunc; // aCallbackFunc is a pointer to a function
// returning int
OBNOXIOUSFUNC anObnoxiousFunc; // anObnoxiousFunc is a pointer to a function
// returning a pointer to a 20-element array
// of pointers to int
Try doing that with a preprocessor macro.
#define defines macros.
typedef defines types.
Now saying that, here are a few differences:
With #define you can define constants that can be used in compile time. The constants can be used with #ifdef to check how the code is compiled, and specialize certain code according to compile parameters.
You can also use #define to declare miniature find-and-replace Macro functions.
typedef can be used to give aliases to types (which you could probably do with #define as well), but it's safer because of the find-and-replace nature of #define constants.
Besides that, you can use forward declaration with typedef which allows you to declare a type that will be used, but isn't yet linked to the file you're writing in.
Preprocessor macros ("#define's") are a lexical replacement tool a la "search and replace". They are entirely agnostic of the programming language and have no understanding what you're trying to do. You can think of them as a glorified copy/paste mechanic -- occasionally that's useful, but you should use it with care.
Typedefs are a C language feature that lets you create aliases for types. This is extremely useful to make complicated compound types (like structs and function pointers) readable and handlable (in C++ there are even situations where you must typedef a type).
For (3): You should always prefer language features over preprocessor macros when that's possible! So always use typedefs for types, and constant values for constants. That way, the compiler can actually interact with you meaningfully. Remember that the compiler is your friend, so you should tell it as much as possible. Preprocessor macros do the exact opposite by hiding your semantics from the compiler.
They are very different, although they are often used to implement custom data types (which is what I am assuming this question is all about).
As pmg mentioned, #define is handled by the pre-processor (like a cut-and-paste operation) before the compiler sees the code, and typedef is interpreted by the compiler.
One of the main differences (at least when it comes to defining data types) is that typedef allows for more specific type checking. For example,
#define defType int
typedef int tdType
defType x;
tdType y;
Here, the compiler sees variable x as an int, but variable y as a data type called 'tdType' that happens to be the same size as an int. If you wrote a function that took a parameter of type defType, the caller could pass a normal int and the compiler wouldn't know the difference. If the function instead took a parameter of type tdType, the compiler would ensure that a variable of the proper type was used during function calls.
Also, some debuggers have the ability to handle typedefs, which can be much more useful than having all custom types listed as their underlying primitive types (as it would be if #define was used instead).
No. typedef is a C keyword that creates an alias for a type. #define is a pre-processor instruction, that creates a text replacement event prior to compilation. When the compiler gets to the code, the original "#defined" word is no longer there. #define is mostly used for macros and global constants.
AFAIK, No.
typedef helps you set up an "alias" to an existing data type. For eg. typedef char chr;
#define is a preprocessor directive used to define macros or general pattern substitutions. For eg. #define MAX 100, substitutes all occurrences of MAX with 100
As mentioned above, there is a key difference between #define and typedef. The right way to think about that is to view a typedef as being a complete "encapsulated" type. It means that you cannot add to it after you have declared it.
You can extend a macro typename with other type specifiers, but not a typedef'd typename:
#define fruit int
unsigned fruit i; // works fine
typedef int fruit;
unsigned fruit i; // illegal
Also, a typedef'd name provides the type for every declator in a declaration.
#define fruit int *
fruit apple, banana;
After macro expansion, the second line becomes:
int *apple, banana;
Apple is a pointer to an int, while banana is an int. In comparison. a typedef like this:
typedef char *fruit;
fruit apple, banana;
declares both apple and banana to be the same. The name on the front is different, but they are both pointers to a char.
Another reason to use typedef (which has only been mentioned briefly in other answers and yet I think is the entire reason typedef was created) is to make debugging easier when using libraries that have custom types. For example, I'll use a type-conversion error. Both the codes below will print a compile-time error saying that a char is not comparable to a string, but in different ways.
typedef char letter;
letter el = 'e';
if(el == "hello");
The above code will print something like the variable "el" of type letter (aka "char") is not compatable with type "char*"
#define letter char
letter el = 'e';
if(el == "hello");
This code will instead print the variable "el" of type char is not compatable with type "char*"
This may seem silly because I'm defining "letter" as "char", but in more complex libraries this can be extremely confusing because pointers to objects like buttons, windows, sound servers, images, and lots of other things are defined as unsigned char *, which would only be debuggable as exactly that when using the #define method.
As everyone said above, they aren't the same. Most of the answers indicate typedef to be more advantageous than #define.
But let me put a plus point of #define :when your code is extremely big, scattered across many files, it's better to use #define; it helps in readability - you can simply preprocess all the code to see the actual type definition of a variable at the place of its declaration itself.