Monday, March 26, 2012

#define vs costants in C

1st Logic:
In ANSI C constants can be defined two ways: through the #define statement and through use of the const modifier. For example, the following two statement, are equivalent:
#define LENGTH 10       /* Length of the square in inches */
const int length = 10;  /* Length of the square in inches */
The const declaration is better because it is in the main part of the C language and provides more protection against mistakes.
Consider the following example:
#define SIZE 10 + 20      /* Size of both tables combined */
const int size = 10 + 20; /* Size of both tables combined */
As you've already seen, the #define statement is a problem. SIZE is a macro and always expands to 10 + 20. The const int size is an integer. It has the value 30. So while the statement:
area = SIZE * SIZE: /* Mistake */
generates the wrong number, the statement:
area = size * size: /* Works */
generates the right number. So the const declaration is less error-prone. Also, if you make a mistake in defining a const , the compiler generates an error message that points at the correct line. With a #define , the error appears when the symbol is used, not when it is defined.
Then why do we have the #define ? Because early compilers did not recognize const declarations. There is still a lot of code out there that was written for these compilers and that should be modernized.
The use of const is preferred over #define for specifying constants.

2nd logic:
One of them informs the preprocessor to do a textual substitution. The other actually declares a (constant) C variable.

A #define is either an immediate value or a macro. A constant is a variable that doesn't change in value. You can delcare a pointer to a const, but not to a #define, although a define could be a pointer (for example "#define PI1234 ((int *)0x1234)".

In C, #defines are local only, so there's no way to make a #define externally available to the linker. Instead, the #define must be included in the source code for all modules that need to access the define. A const variable can be global and accessed via other linked modules, but requires a memory access and occupies space. In assembly, global equates are possible, and linkers typically generate global equates to indicate the bounds of key points within the code, like the start and end of data and code. Global equates don't require a memory access and don't occupy any space.

Within a module, a C compiler could optimize a const as if it were a #define, if there are no pointers declared to the constant. In CPU terms, the const would become an "immediate" value. Other alternatives is that a const variable could be placed in the code area as opposed to the data area since it doesn't change. On some machines, declaring a ponter to a constant could cause an exception if you tried to modify the constant via the pointer (if the constant were placed in a read-only code section).

No comments:

Post a Comment