I have some legacy code that contains this typedef:
typedef enum simple_op_enum {
#define SOP(OPCODE, NAME, FORM, SUIFOP) OPCODE ,
#include "simple_ops.def"
LAST_OP
} simple_op;
The #include file contains several lines of the form:
/* no operand instructions */
SOP( NOP_OP, "nop ", BASE_FORM, io_nop)
The token "simple_op" occurs later in a struct:
typedef struct simple_instr_struct {
simple_op opcode; /* the opcode */
There are several things I don't understand:
What is accomplished by having a comma at the end of the #define statement? I thought that was illegal.
What is being accomplished by the enum, especially LAST_OP
How do I access the value of opcode in a simple_instr_struct?
It's not illegal, it's part of what the preprocessor will replace all instances of SOP(x, y, z) with.
It's creating an enumeration with the contents in simple_ops.def. Because the contents of that file are SOP(w, x, y, z) they will all turn into w, and the enum will be:
typedef enum simple_op_enum {
NOP_OP , // <- notice the space before the comma, like the #define does
... // the others
LAST_OP
} simple_op;
It also makes LAST_OP the last enumeration value. This is probably so the code can use LAST_OP to determine how many enum values there are (or the highest enum value, or something like that).
This #include thing is a clever trick so that the definitions can be all in the same place (the file) and the code that #includes it just defines SOP to be whatever it needs it to be. Then modifying that one file will affect the entirety of the code that needs it and the code uses them in whatever way it needs. For instance, some code might only need the name, so it would define SOP as #define SOP(w, x, y, z) x to extract the name.
3) You can access it by doing simple_instr_struct_instance.opcode
If in doubt about macros, you can always use the preprocessor to see how they expand:
gcc -E file.c -o file.txt
The output will be large if there are many header files included, but you will find your macros in there somewhere - probably towards the end
Comma at end of #define is legal. it's part of the macro. constants of enums are separates by comma, and this macro worries to that.
enum is just a var that can contain any of the values you specify in the enum declaration. since them are translated to numbers, LAST_OP will be equal to the number of possibilities.
you can access the member like:
struct simple_instr_struct a;
a.opcode=LAST_OP;
The comma is just part of the text replacement that will occur when the macro is used. In this case, it's to add a comma after each opcode, so that the list will make valid enum syntax.
The result of the #define and #include is an enumeration that looks like:
typedef enum simple_op_enum {
NOP_OP,
.
.
.
LAST_OP
} simple_op;
You can see the same by looking at the output of running your source code through the C preprocessor. LAST_OP is just the last entry in your new enumeration.
You'll need to define a variable of that type:
struct simple_instr_struct myStruct;
and then access the field you care about:
myStruct.opcode
it will extract out the opcodes as enums
enums need comma seperating, so its taking the OPCODE and putting a , after it which effectively generates
typedef enum simple_op_enum {
NOP_OP, BLAH , WHATEVER , ANOTHER ,
LAST_OP
} simple_op;
The point of the enum is to have an enum of all the opcodes available.
LAST_OP is useful for knowing things like how many opcodes you end up with, and also means there is no dangling comma for the last thing in the enum list.
if you have a instance of the struct , 'blah', then you get it by going blah.opcode = NOP_OP;
Related
While trying to write a macro inside an enum, in C.
We have to sometimes write name of macro, above macro definition, why ?
#include <stdio.h>
enum month {
MSD //If I remove or comment this line, code does not work, why?
#define MSD 7
};
void main() {
printf("%d\n", MSD);
}
If we remove the 5th line of code, i.e. "MSD". We get error
empty enum is invalid. Why is this happening, can anyone explain, please ?
Macros and enums are separate things. Most importantly, a macro only exists at compile time so the preprocessor will replace all instances of MSD in the following code with 7 exactly as if you'd done a find-and-replace in your editor. Enums, on the other hand, exist at runtime and are generally numeric values mapped to symbols.
Now, with your code as you have it the MSD in your printf("%d\n", MSD); is replaced with 7 at compile time so the enum is never actually used. If you remove the 5th line of code the compiler sees an empty enum because the #define MSD 7 macro is filtered out by the preprocessor leaving nothing else inside the enum.
If intention is to define a enum. we can define as below.
(we can define MSD in form of enum of a #define, either one of this is required to use "MSD" in code for value 7)
#include <stdio.h>
enum month {
MSD = 7,
TST = 1 // added just for ref
};
// in linux requires int main() { <code> return 0;}
void main() {
printf("enum MSD == %d\n", MSD);
}
I was reading a source code of header file and wondered why have they written macros that way, in which I have posted
I think you may have misread a header file that was doing this slightly different thing:
enum thing_enum {
THING_ONE = 1,
#define THING_ONE THING_ONE
THING_TWO,
#define THING_TWO THING_TWO
// etc
};
This is the same as writing a normal enum declaration
enum thing_enum {
THING_ONE = 1,
THING_TWO,
// etc
};
and then, also, defining each enumerator as a macro that expands to itself:
#define THING_ONE THING_ONE
#define THING_TWO THING_TWO
// etc
Written this way, it should be clearer why you get an error when you comment out the ‘MSD’ line in your code: the #define doesn’t contribute anything to the definition of the enum, so you have an enum with no values, which the language does not allow.
Header files do this odd-looking thing because it makes each THING_ constant be both a macro and an enum value, which means you can use all the features of enum to set their values (e.g. in my example THING_TWO is equal to 2 without my having had to say so explicitly) and the names will be made visible to the debugger, but it’s still possible to check for the existence of a particular constant with #ifdef.
The disadvantages are that it doubles the length of the definition of the set of constants, you cannot make the type of each constant be anything other than int, and the constants cannot be used in an #if expression (except as the argument of defined).
(Note: A macro that expands to itself does not put the preprocessor into an infinite loop. THING_ONE is replaced with THING_ONE once and then the preprocessor moves on to the next token.)
MSD has nothing do with declaring above #define MSD 7, the reason for error is that enum{ }; should not be empty.
you get the below error if enum is empty.
main.c:12:1: error: empty enum is invalid
};
Try declaring another enum value there instead of MSD, it will work as shown below.
#defines are text replacements, they dont need any declarations, just definitions.
#include <stdio.h>
enum month {
x = 0
//MSD //If I remove or comment this variable declaration, code does not work, why?
#define MSD 7
};
void main() {
printf("%d\n", MSD);
}
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.
We all know that we can "mash" together string literals in C without most compilers troubling us, for example char[] result = "a" "b"; // result = "ab". I want to generalize this idea to structs.
Suppose I have the following structs:
typedef struct s1 {
char a;
int b;
} s1_t;
typedef struct s2 {
int c;
} s2_t;
Effectively I want to declare byte arrays that are arbitrary combinations of s1_t and s2_t. Is this reasonably possible? I would prefer not to use unions. The contents of the structs will be known at compile time.
We all know that we can "mash" together string literals in C without most compilers troubling us
Indeed, no conforming C compiler will complain, as the semantics of such constructs are defined explicitly by the standard(s). I mention this to highlight that the result is not accidental, subject to luck or compiler whim, or any such thing, as your comments seem to allow as possibilities.
Effectively I want to declare byte arrays that are arbitrary combinations of [two structure types]. Is this reasonably possible? I would prefer not to use unions.
Strictly speaking, it is not possible. You cannot use struct literals in any combination to initialize a byte array. You can achieve something fairly close in C99 or later using unions, and if you want compile-time initialization from struct literals, then I don't see any other option. It would look like this:
typedef union {
s1_t s1;
s2_t s2;
} s_u;
s_u array[] = {
{ .s1 = (s1_t) { 'a', 42 } },
{ .s1 = (s1_t) { 'b', 17 } },
{ .s2 = (s2_t) { 1856 } },
{ .s1 = (s1_t) { 'Q', -1 } }
};
unsigned char *byte_array = (unsigned char *)array;
I suppose, however, that your reason for wanting to avoid unions is to pack together struct representations of different sizes without padding. This is not possible. Indeed, even with only one struct type, it is not necessarily possible to arrange instances without any padding between last element of one instance and the first of the next instance. It may not be easy even to force it with memcpy(), as the representations of your structs can have both trailing padding and internal padding, all accounted in their sizes. And don't forget that the values of any padding bytes are undefined.
You describe the result you're after as "sequential bytecode" and "serialized structs" (emphasis added). I can't be certain what "serialized" means to you in this context, but to me it normally means something quite different from "internal representation". In fact, avoiding dependency on internal representation is one of the main reasons for serialization.
If your objective conforms to my idea of serialization, then your best bet for avoiding making your users write bytecode is to provide them a bytecode compiler, with input and output in whatever forms will be most convenient.
It may be possible to achieve something like what you're after with some nasty macro-based clunkery, if your data structure is defined in a separate file which code can #includeed multiple times while different macros are in effect.
Suppose for example that your data is in a file foo.dat of the following format:
INTS(1,2)
IDBL(-4,3)
INTS(5,23)
Items should be listed on separate lines, with no semicolons.
One could start by doing something like:
#define INTS(x,y) INT_PAIR Field ## __LINE__;
#define IDBL(x,y) INT_DBL Field ## __LINE__;
struct ALL_DATA {
#include "foo.dat"
int END_OF_DATA;
};
#undef INTS
#undef INTS
This would then be followed by:
#define INTS(x,y) {(x),(y)},
#define IDBL(x,y) {(x),(y)},
const struct ALL_DATA all_data = {
#include "foo.dat"
0};
#undef INTS
#undef INTS
At that point one would have a compile-time constant structure containing a concatenation of a mixture of the other structure types, which could be parsed at run-time if it was constructed according to some form of known rules (e.g. the first value is positive for all int/int pairs, negative for all int/double pairs, and zero for end-of-data).
If one wanted to have an array containing the starting offsets of all the items (in int-sized units) from the start of the structure, one could use a couple more inclusions:
#define INTS(x,y) INT_PAIR FIELD_ID_ ## __LINE__, dummy1x ## __LINE__,
#define IDBL(x,y) INT_DBL FIELD_ID_ ## __LINE__, \
dummy1x ## __LINE__, dummy2x ## __LINE__,
enum DATA_IDS {
#include "foo.dat"
dummy_end_id};
#undef INTS
#undef INTS
#define INTS(x,y) FIELD_ID_ ## __LINE__,
#define IDBL(x,y) FIELD_ID_ ## __LINE__,
unsigned int data_offsets[] = {
#include "foo.dat"
-1};
#undef INTS
#undef INTS
I don't know any way to make this work without either abusing the __LINE__ directive or requiring that each line of the data file supply a unique identifier name; which approach is preferable could be open to discussion.
Please share with us your favorite, and most general, PRINT or DEBUG macro
applicable to all (or almost all) variables in different types and to arrays in C. The macro
can have any number of parameters (though 1-3 are preferred); if it increases
descriptive power at all, C99 features can be assumed.
#define PRINT(var, ...) \
...
Let's begin!
For C++, template function can be much more powerful than macro.
template <typename T>
std::string tostring(const T& t);
The drawback of template argument is that it cannot distinguish between typedef aliases:
typedef LONG HRESULT;
For C, I think there is nothing you can do, without changing your structs. If you have control over the struct definitions, here are two tricks:
Add a field to the beginning of the struct, and set the field to a value that uniquely identifies the type of the structure, which can be used by the tostring function to choose the appropriate printing code.
typedef struct abcde
{
int unique_struct_type_id; // assign this to a number that represents "abcde"
};
A similar method is to pass in a function pointer for printing the struct.
struct abcde
{
void (*print_fn) (abcde* p); // assign this to the printing function for "abcde"
}
#define PRINT_STRUCT(s) s->print_fn(s)
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.