defining a function with #define
-
Hi, Please help me understanding the following declaration:
#define EVENBYTE( i ) ((i+7)/8*8)
It represents the definition of function? If for example I call EVENBYTE( 1 ), the result will be ((1+7)/8*8)? From where I have extracted de code, the EVENBYTE was called in that way:
int nIconBytes = (EVENBYTE(nWidth)/8)*nHeight;
I don't understand what this kind of declaring is and why to do it in that mode? Thank you in advance.
-
Hi, Please help me understanding the following declaration:
#define EVENBYTE( i ) ((i+7)/8*8)
It represents the definition of function? If for example I call EVENBYTE( 1 ), the result will be ((1+7)/8*8)? From where I have extracted de code, the EVENBYTE was called in that way:
int nIconBytes = (EVENBYTE(nWidth)/8)*nHeight;
I don't understand what this kind of declaring is and why to do it in that mode? Thank you in advance.
No, it is not a function, it is a macro definition. While, in your case a function defined as:
int evenbyte (int i) {return (i+7)/8*8;}
would do the same thing, there is an important difference: a macro definition is expanded at compile time while a function is compiled and later on called at runtime. When to use one over the other is a question of optimization speed vs memory: a macro definition like your would not incur the overhead of a call but might produce larger code. Meanwhile a function definition would produce smaller code but might take longer to execute. To solve these type of issues, C++ has introduced inline functions, so in C++ you can write
inline int evenbyte (int i) {return (i+7)/8*8;}
and you leave the compiler the choice of expanding it inline (like a macro definition) or make it a function and call it. One more thing: the macro definition is insensitive to the type of argument. That is both a good thing and a bad thing like in the examples below:
int i1 = 3;
int e1 = EVENBYTE (i1); //calling macro with an int argument yields an int result
long i2 = 129;
long e2 = EVENBYTE (e2); //calling macro with a long argument yields a long resultint e3 = EVENBYTE ("abc"); //generates some obscure error message
To accomplish the same thing in C++ you would have to use a function template:
template
T evenbyte (T i) { return (i+7)/8*8;}Mircea
-
Hi, Please help me understanding the following declaration:
#define EVENBYTE( i ) ((i+7)/8*8)
It represents the definition of function? If for example I call EVENBYTE( 1 ), the result will be ((1+7)/8*8)? From where I have extracted de code, the EVENBYTE was called in that way:
int nIconBytes = (EVENBYTE(nWidth)/8)*nHeight;
I don't understand what this kind of declaring is and why to do it in that mode? Thank you in advance.
-
No, it is not a function, it is a macro definition. While, in your case a function defined as:
int evenbyte (int i) {return (i+7)/8*8;}
would do the same thing, there is an important difference: a macro definition is expanded at compile time while a function is compiled and later on called at runtime. When to use one over the other is a question of optimization speed vs memory: a macro definition like your would not incur the overhead of a call but might produce larger code. Meanwhile a function definition would produce smaller code but might take longer to execute. To solve these type of issues, C++ has introduced inline functions, so in C++ you can write
inline int evenbyte (int i) {return (i+7)/8*8;}
and you leave the compiler the choice of expanding it inline (like a macro definition) or make it a function and call it. One more thing: the macro definition is insensitive to the type of argument. That is both a good thing and a bad thing like in the examples below:
int i1 = 3;
int e1 = EVENBYTE (i1); //calling macro with an int argument yields an int result
long i2 = 129;
long e2 = EVENBYTE (e2); //calling macro with a long argument yields a long resultint e3 = EVENBYTE ("abc"); //generates some obscure error message
To accomplish the same thing in C++ you would have to use a function template:
template
T evenbyte (T i) { return (i+7)/8*8;}Mircea
Also worth noting: A macro does not define its own scope, the way a function does. It could refer to other symbols, say,
#define PLUSX(i) (i + x)
Which x is added? That depends on where PLUSX is used. In one place it could be a different x than in another place. In a third place, there may be no x defined at all, and you get a compilation error, even if the two first uses of PLUSX went without any error. A define is a pure textual replacement. If you in your code editor replace 'PLUSX(i)' with '(i + x)' (and change the 'i' in the replacement text to whatever was the name of your actual argument), you are doing by hand the work of the C preprocessor. Or in your case, if in your editor you replace
int nIconBytes = (EVENBYTE(nWidth)/8)*nHeight;
with
int nIconBytes = (((nWidth+7)/8*8)/8)*nHeight;
then you get the exact same result as with the #define. Note: I am certainly not suggesting that referring to non-argument variables from macros is a good idea (usually is is not), but understanding how macros differ from functions includes understanding how such references would work. Personal opinion: #define is among the most mis-used features of the C language. Except for giving symbolic names to simple constants, you should try to avoid it as far as possible.
-
Also worth noting: A macro does not define its own scope, the way a function does. It could refer to other symbols, say,
#define PLUSX(i) (i + x)
Which x is added? That depends on where PLUSX is used. In one place it could be a different x than in another place. In a third place, there may be no x defined at all, and you get a compilation error, even if the two first uses of PLUSX went without any error. A define is a pure textual replacement. If you in your code editor replace 'PLUSX(i)' with '(i + x)' (and change the 'i' in the replacement text to whatever was the name of your actual argument), you are doing by hand the work of the C preprocessor. Or in your case, if in your editor you replace
int nIconBytes = (EVENBYTE(nWidth)/8)*nHeight;
with
int nIconBytes = (((nWidth+7)/8*8)/8)*nHeight;
then you get the exact same result as with the #define. Note: I am certainly not suggesting that referring to non-argument variables from macros is a good idea (usually is is not), but understanding how macros differ from functions includes understanding how such references would work. Personal opinion: #define is among the most mis-used features of the C language. Except for giving symbolic names to simple constants, you should try to avoid it as far as possible.
In C,
#define
is sometimes used to do the same thing as templates in C++, which I can understand. In C++,#define
shouldn't be used that way, but C hackers use their preprocessor crapola in C++. It shouldn't even be used to define constants, especially afterconstexpr
showed up.Robust Services Core | Software Techniques for Lemmings | Articles
The fox knows many things, but the hedgehog knows one big thing. -
In C,
#define
is sometimes used to do the same thing as templates in C++, which I can understand. In C++,#define
shouldn't be used that way, but C hackers use their preprocessor crapola in C++. It shouldn't even be used to define constants, especially afterconstexpr
showed up.Robust Services Core | Software Techniques for Lemmings | Articles
The fox knows many things, but the hedgehog knows one big thing. -
coco243 wrote:
Please help me understanding the following declaration
Kinda looks like something used for calculating Image stride[^].