C programming language Tutorial-Page4
Macros -Definitions
• A macro is a fragment of code which has been given a name. Whenever the name is used, it is replaced by the contents of the macro.
• This replacement is done by the C-preprocessor
• There are two kinds of macros. They differ mostly in what they look like and when they are used.
• Object-like macros resemble data objects when used
• Function-like macros resemble function calls
• Macros are used to substitute repetitive values, or fragments of code which cannot be made function; or converting them to a function may be costly.
Macros -Object-like Macros
• An object-like macro is a simple identifier which will be replaced by a code fragment. It is called object-like because it looks like a data object in code that uses it. They are most commonly used to give symbolic names to numeric constants.
• #define BUFFER_SIZE 1024 defines a macro named BUFFER_SIZE as an abbreviation for the token 1024.
• If somewhere after this '#define' directive there comes a C statement of the form
foo = (char *) malloc (BUFFER_SIZE);
then the C preprocessor will recognize and expand the macro BUFFER_SIZE. The C compiler will see the same tokens as it would if you had written
foo = (char *) malloc (1024);
• By convention, macro names are written in uppercase.
Programs are easier to read when it is possible to tell at a glance which names are macros.
The macro's body ends at the end of the '#define' line. You may continue
the definition onto multiple lines, if necessary, using backslash-newline.
When the macro is expanded, however, it will all come out on one line.
For example,
#define NUMBERS 1, \
2, \
3
int x[] = { NUMBERS }; ==> int x[] = { 1, 2, 3 };
Remember that there shouldn't be any space at the end of the \
when you continue the macro in multiple lines.
The C preprocessor scans your program sequentially.
Macro definitions take effect at the place you write them.
Therefore, the following input to the C preprocessor
foo = X;
#define X 4
bar = X;
produces
foo = X; bar = 4;
What will the value of x in the below program.
#define BUFSIZE (1020)
#define TABLESIZE (BUFSIZE)
#undef BUFSIZE
#define BUFSIZE (37)
int main(void)
{
int x = TABLESIZE;
printf ("x= %d\n");
}
Macros - Function-like Macros
Function-like macros can take arguments, just like true functions.
To define a macro that uses arguments, you insert parameters
between the pair of parentheses in the macro definition that
make the macro function-like. The parameters must be valid C identifiers,
separated by commas and optionally whitespace.
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
x = MIN(a, b); ==> x = ((a) < (b) ? (a) : (b));
y = MIN(1, 2); ==> y = ((1) < (2) ? (1) : (2));
z = MIN(a + 28, *p); ==> z = ((a + 28) < (*p) ? (a + 28) : (*p));
Macros -Concatenation
It is often useful to merge two tokens into one while expanding macros. This is called token pasting or token concatenation. The '##' preprocessing operator performs token pasting. When a macro is expanded, the two tokens on either side of each '##' operator are combined into a single token, which then replaces the '##' and the two original tokens in the macro expansion.
Typedef -Definition and uses
A typedef declaration lets you define your own identifiers that can be used in
place of type specifiers such as int, float, and double.
A typedef declaration does not reserve storage. The names you define using
typedef are not new data types, but synonyms for the data types or combinations
of data types they represent.
When an object is defined using a typedef identifier, the properties of
the defined object are exactly the same as if the object were defined by
explicitly listing the data type associated with the identifier.
It means that
typedef unsigned char uint8;
uint8 abcd;
and
unsigned char abcd;
are the same
typedef allows users to define data types which they want.
Using typedef can make code easier to read and easier to port
to a new machine. But no new physical data type is created.