473,503 Members | 3,715 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Function-like macro

Hi,

How do i make an if/then/else macro act as a function
so that the whole thing looks like the return value?

I tried this lame attempt for starters:

#define A_FROM_B(b) \
( \
if(b < 10) { \
a = b; \
} \
else { \
a = 2*b; \
}, \
a; \
)
Nov 14 '05 #1
17 2135
Russell Shaw <rjshawN_o@s_pam.netspace.net.au> wrote:
How do i make an if/then/else macro act as a function
so that the whole thing looks like the return value?
You don't. That's what the ?: operator is for.
I tried this lame attempt for starters:

#define A_FROM_B(b) \
( \
if(b < 10) { \
a = b; \
a? What is a? What happens if I call this macro in a function where a is
a struct?
} \
else { \
a = 2*b; \
}, \
a; \
)


#define A_FROM_B(b) ((b)<10? (b): 2*(b))

Note the parens around b in the definition of the macro. They will save
your bacon some day when you decide to call A_FROM_B(x+10).

Richard
Nov 14 '05 #2
Richard Bos wrote:
Russell Shaw <rjshawN_o@s_pam.netspace.net.au> wrote:
How do i make an if/then/else macro act as a function
so that the whole thing looks like the return value?


You don't. That's what the ?: operator is for.
I tried this lame attempt for starters:

#define A_FROM_B(b) \
( \
if(b < 10) { \
a = b; \


a? What is a? What happens if I call this macro in a function where a is
a struct?


Like i said, it's a lame one;)
} \
else { \
a = 2*b; \
}, \
a; \
)


#define A_FROM_B(b) ((b)<10? (b): 2*(b))

Note the parens around b in the definition of the macro. They will save
your bacon some day when you decide to call A_FROM_B(x+10).

Richard


What do i do with things that contain more complex statements like:

if(size > 0x1ff) {
size_t sz = size;
for(ndx = 0; ndx < 32; ndx++) {
if(sz <= 0) {
break;
}
sz >>= 1;
}
ndx -= 8;
ndx <<= 9;
}
else {
ndx = size;
}

Do i have to make it into a function?
Nov 14 '05 #3
On Tue, 24 May 2005 20:24:28 +1000,
Russell Shaw <rjshawN_o@s_pam.netspace.net.au> wrote:


Do i have to make it into a function?


An inline function wouldn't be such a bad alternative if it is available
with your compiler. Otherwise, "do { ... } while (0)" is a common
ideom for making a function like macro.

Villy
Nov 14 '05 #4
Russell Shaw <rjshawN_o@s_pam.netspace.net.au> wrote:
Richard Bos wrote:
Russell Shaw <rjshawN_o@s_pam.netspace.net.au> wrote:
How do i make an if/then/else macro act as a function
so that the whole thing looks like the return value?
You don't. That's what the ?: operator is for.
I tried this lame attempt for starters:

#define A_FROM_B(b) \
( \
if(b < 10) { \
a = b; \


a? What is a? What happens if I call this macro in a function where a is
a struct? Like i said, it's a lame one;)
} \
else { \
a = 2*b; \
}, \
a; \
)


#define A_FROM_B(b) ((b)<10? (b): 2*(b))

Note the parens around b in the definition of the macro. They will save
your bacon some day when you decide to call A_FROM_B(x+10).

Richard

What do i do with things that contain more complex statements like: if(size > 0x1ff) {
size_t sz = size;
for(ndx = 0; ndx < 32; ndx++) {
if(sz <= 0) {
break;
}
sz >>= 1;
}
ndx -= 8;
ndx <<= 9;
}
else {
ndx = size;
} Do i have to make it into a function?


You can make a macro out of that, e.g.

#defined STRANGE_MACRO( size, ndx ) \
do { \
if ( ( size ) > 0x1ff) { \
size_t sz = ( size ); \
for ( ndx = 0; ndx < 32; ndx++ ) { \
if ( sz <= 0 ) \
break; \
sz >>= 1; \
} \
ndx -= 8; \
ndx <<= 9; \
} \
else \
ndx = ( size ); \
} while ( 0 ) \

but I would rather recommend to make that a function. Macros can
easily break when not written and used very carefully. If you e.g.
call it as

STRANGE_MACRO( size++, ndx );

then 'size' gets incremented two or three times instead of just
once as you would expect from a function call because a macro i
a simple text replacement (you could avoid that here by introdu-
cing another variable in the block and assigning the value of
'size' to it just once instead of evaluating it several times
in the macro). And, of course, if you try to call it like this

STRANGE_MACRO( size, ndx + 1 );

you'll ge a syntax error that's probably very hard to find. So why
not make the whole thing into a function?

BTW, in that macro you use a shift operation on 'sz' but also test
it for being less or equal to 0. But you can only use shift operations
safely on unsigned integers.
Regards, Jens
--
\ Jens Thoms Toerring ___ Je***********@physik.fu-berlin.de
\__________________________ http://www.toerring.de
Nov 14 '05 #5
Russell Shaw wrote:

How do i make an if/then/else macro act as a function
so that the whole thing looks like the return value?

I tried this lame attempt for starters:

#define A_FROM_B(b) \
( \
if(b < 10) { \
a = b; \
} \
else { \
a = 2*b; \
}, \
a; \
)


try:

#define A_FROM_B(b) do {\
if (b < 10) a = b; \
else { \
a = 2*b; \
} \
} while (0)

The general form is "do { <stuff> } while (0)", and you are free to
write legal code for <stuff>. It does not return a usable value.

--
Some useful references about C:
<http://www.ungerhu.com/jxh/clc.welcome.txt>
<http://www.eskimo.com/~scs/C-faq/top.html>
<http://benpfaff.org/writings/clc/off-topic.html>
<http://anubis.dkuug.dk/jtc1/sc22/wg14/www/docs/n869/> (C99)
<http://www.dinkumware.com/refxc.html> (C-library}
<http://gcc.gnu.org/onlinedocs/> (GNU docs)
Nov 14 '05 #6
Russell Shaw <rjshawN_o@s_pam.netspace.net.au> wrote:
Richard Bos wrote:
#define A_FROM_B(b) ((b)<10? (b): 2*(b))

Note the parens around b in the definition of the macro. They will save
your bacon some day when you decide to call A_FROM_B(x+10).


What do i do with things that contain more complex statements like:

if(size > 0x1ff) {
size_t sz = size;
for(ndx = 0; ndx < 32; ndx++) {
if(sz <= 0) {
break;
}
sz >>= 1;
}
ndx -= 8;
ndx <<= 9;
}
else {
ndx = size;
}

Do i have to make it into a function?


Have to is strong, but in practice that would be the best solution.
Modern compilers are quite good at optimising, so a function this size
would probably be inlined automatically wherever that is more efficient.

Richard
Nov 14 '05 #7
Villy Kruse <ve*@station02.ohout.pharmapartners.nl> wrote:
On Tue, 24 May 2005 20:24:28 +1000,
Russell Shaw <rjshawN_o@s_pam.netspace.net.au> wrote:
Do i have to make it into a function?


An inline function wouldn't be such a bad alternative if it is available
with your compiler. Otherwise, "do { ... } while (0)" is a common
ideom for making a function like macro.


True, but it has one drawback: you can't return a value from one, so it
acts as a statement block, not as a function call.

Richard
Nov 14 '05 #8
Russell Shaw <rjshawN_o@s_pam.netspace.net.au> wrote:
# Hi,
#
# How do i make an if/then/else macro act as a function
# so that the whole thing looks like the return value?

You can turn the following statements into expressions. If you mind the precedence,
you can reduce the number of parentheses.

a; b (a,b)
{a} (a)
if (a) b; else c ((a)?(b):(c))
expression; (expression)

With declarations and other statements, you're screwed.

Note that "a = b" is an expression. The statement "a = b;" can be converted to
"a = b".

# #define A_FROM_B(b) \
# ( \
# if(b < 10) { \
# a = b; \
# } \
# else { \
# a = 2*b; \
# }, \
# a; \
# )

( \
(b < 10) ? ( \
a = b \
) \
: ( \
a = 2*b \
), \
a \
)

--
SM Ryan http://www.rawbw.com/~wyrmwif/
Elvis was an artist. But that didn't stop him from joining the service
in time of war. That's why he is the king, and you're a shmuck.
Nov 14 '05 #9
Russell Shaw <rjshawN_o@s_pam.netspace.net.au> writes:
How do i make an if/then/else macro act as a function
so that the whole thing looks like the return value?

I tried this lame attempt for starters:

#define A_FROM_B(b) \
( \
if(b < 10) { \
a = b; \
} \
else { \
a = 2*b; \
}, \
a; \
)


Many macros written in statement form can be written fairly easily in
expression form instead. Is there any reason

#define A_FROM_B(b) (a = (b)<10 ? (b) : 2*(b))

doesn't meet your needs in this case?

As a matter of good form I'd usually prefer that the assigned-to
variable be made explicit:

#define ASSIGN_BAROQUELY(a,b) ((a) = (b)<10 ? (b) : 2*(b))

but that is a separate discussion.

Those macro definitions that can't be written in expression form and
that need to return a value are probably better written as functions,
whether inline functions are available or not.
Nov 14 '05 #10

"Russell Shaw" <rjshawN_o@s_pam.netspace.net.au> wrote
How do i make an if/then/else macro act as a function
so that the whole thing looks like the return value?

I tried this lame attempt for starters:

#define A_FROM_B(b) \
( \
if(b < 10) { \
a = b; \
} \
else { \
a = 2*b; \
}, \
a; \
)


#define A_FROM_B(b) ((b) < 10 ? (b) : (2 * (b)))
Nov 14 '05 #11
Russell> How do i make an if/then/else macro act as a function so
Russell> that the whole thing looks like the return value?

Others have already pointed out that you're probably much better off
using an inline function. It's more easily readable and editable.
That said, GCC does have a non-standard extension that allows you to
do what you want:

#define A_FROM_B(b) \
({ \
int __b = (b); \
int __a; \
if (__b < 10) \
__a = __b; \
else \
__a = 2*__b; \
__a; \
})

A few notes:

* I haven't compiled the above code so I may have a couple of
typos in it. See Statement Exprs in the gcc info pages.

* I introduced the __b variable to prevent multiple evaluation
of b. (Functions get you this for free, of course.)

* The value of the macro is the the last "bare" expression in
the block.

* As I mentioned, as far as I know this is non-standard.

* GCC has a couple of other nifty extensions that work well
together with this extension. Especially see the gcc info
on typeof().

* Because macros are based on textual substitution, it's a
good idea to introduce local variable names that aren't
likely to collide with names used inside the macro
arguments. (Again, functions completely avoid this issue.)

Dale.
Nov 14 '05 #12
Dale Hagglund wrote:
Russell> How do i make an if/then/else macro act as a function so
Russell> that the whole thing looks like the return value?

Others have already pointed out that you're probably much better off
using an inline function. It's more easily readable and editable.
That said, GCC does have a non-standard extension that allows you to
do what you want:

#define A_FROM_B(b) \
({ \
int __b = (b); \
int __a; \
if (__b < 10) \
__a = __b; \
else \
__a = 2*__b; \
__a; \
})

A few notes:

* I haven't compiled the above code so I may have a couple of
typos in it. See Statement Exprs in the gcc info pages.

* I introduced the __b variable to prevent multiple evaluation
of b. (Functions get you this for free, of course.)

* The value of the macro is the the last "bare" expression in
the block.

* As I mentioned, as far as I know this is non-standard.

* GCC has a couple of other nifty extensions that work well
together with this extension. Especially see the gcc info
on typeof().

* Because macros are based on textual substitution, it's a
good idea to introduce local variable names that aren't
likely to collide with names used inside the macro
arguments. (Again, functions completely avoid this issue.)

Dale.


Interesting, it is in gcc-3.4 info help 5.1 Statements and Declarations in Expressions.

Does a curly-bracket block {...} have a value in standard C? I've been looking for
a long time.

The macro above works (i tested it).
Nov 14 '05 #13
[My example of gcc statement expression syntax deleted. --rdh]

Russell> Does a curly-bracket block {...} have a value in standard
Russell> C?

Nope. As far as I know its a gcc-only extension.

Dale.
Nov 14 '05 #14
Russell Shaw <rjshawN_o@s_pam.netspace.net.au> wrote:
Dale Hagglund wrote:
* The value of the macro is the the last "bare" expression in
the block.

* As I mentioned, as far as I know this is non-standard.
Interesting, it is in gcc-3.4 info help 5.1 Statements and Declarations in Expressions. Does a curly-bracket block {...} have a value in standard C? I've been
looking for a long time.


No, a block (compound statement) isn't an expression and thus has no
value. So something like

int i = { 1; };

or

int i = ( { 1; } );

or variations of these aren't standard C. gcc lets you use the second
version, i.e. a compound statement enclosed in parentheses where the
value of the last expression in the block is taken to be the value of
of the whole construct, as an extension only (that's why it is listed
in the info pages under "C Extensions";-)

Regards, Jens
--
\ Jens Thoms Toerring ___ Je***********@physik.fu-berlin.de
\__________________________ http://www.toerring.de
Nov 14 '05 #15
Dale Hagglund <da***********@gmail.com> wrote:
Others have already pointed out that you're probably much better off
using an inline function. It's more easily readable and editable.
That said, GCC does have a non-standard extension that allows you to
do what you want:

#define A_FROM_B(b) \
({ \
int __b = (b); \
int __a; \
if (__b < 10) \
__a = __b; \
else \
__a = 2*__b; \
__a; \
}) * I introduced the __b variable to prevent multiple evaluation
of b. (Functions get you this for free, of course.)
Unfortunately it also makes the macro non-portable, since all
identifiers starting with __ (or _ plus capital letter) are reserved for
the implementation. __b is simple enough that it could clash with
something defined in a system header.
* As I mentioned, as far as I know this is non-standard.
'tis.
* Because macros are based on textual substitution, it's a
good idea to introduce local variable names that aren't
likely to collide with names used inside the macro
arguments. (Again, functions completely avoid this issue.)


But make sure they're yours to use.

Richard
Nov 14 '05 #16
Richard Bos wrote:
#define A_FROM_B(b) ((b)<10? (b): 2*(b))

Note the parens around b in the definition of the macro.
They will save
your bacon some day when you decide to call A_FROM_B(x+10).


Trivia point:
Only the first and last pair are needed for bacon saving.

#define A_FROM_B(b) ((b) < 10 ? b : 2 * (b))

? b :
means the same thing as
?(b):

--
pete
Nov 14 '05 #17
pete <pf*****@mindspring.com> wrote:
Richard Bos wrote:
#define A_FROM_B(b) ((b)<10? (b): 2*(b))

Note the parens around b in the definition of the macro.
They will save
your bacon some day when you decide to call A_FROM_B(x+10).


Trivia point:
Only the first and last pair are needed for bacon saving.

#define A_FROM_B(b) ((b) < 10 ? b : 2 * (b))

? b :
means the same thing as
?(b):


In this case, perhaps. Howsoever, I'd advise getting into the habit of
parenthesisising anyway, for psychobabblical reasons.

Richard
Nov 14 '05 #18

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
2868
by: | last post by:
OK: Purpose: Using user's input and 3 recursive functions, construct an hour glass figure. Main can only have user input, loops and function calls. Recursive function 1 takes input and displays...
5
2143
by: amit kumar | last post by:
I am calling a function which returns pointer to a map. The declaration of the map is map<int,vectxyz*>. vectxyz is a vector containing pointer to a class xyz. For map<int,vectxyz*>* p1 In the...
37
4944
by: Ben | last post by:
Hi, there. Recently I was working on a problem where we want to save generic closures in a data structure (a vector). The closure should work for any data type and any method with pre-defined...
16
16197
by: WittyGuy | last post by:
Hi, What is the major difference between function overloading and function templates? Thanks! http://www.gotw.ca/resources/clcm.htm for info about ]
2
1805
by: Joe | last post by:
I have 3 functions: ClientInfoA is doing something ClientInfoB is doing something SelectFunction2Run is a function to determine which function needed to run based on the value of the variable...
8
5077
by: Olov Johansson | last post by:
I just found out that JavaScript 1.5 (I tested this with Firefox 1.0.7 and Konqueror 3.5) has support not only for standard function definitions, function expressions (lambdas) and Function...
2
5300
by: f rom | last post by:
----- Forwarded Message ---- From: Josiah Carlson <jcarlson@uci.edu> To: f rom <etaoinbe@yahoo.com>; wxpython-users@lists.wxwidgets.org Sent: Monday, December 4, 2006 10:03:28 PM Subject: Re: ...
28
4272
by: Larax | last post by:
Best explanation of my question will be an example, look below at this simple function: function SetEventHandler(element) { // some operations on element element.onclick = function(event) {
7
3183
by: VK | last post by:
I was getting this effect N times but each time I was in rush to just make it work, and later I coudn't recall anymore what was the original state I was working around. This time I nailed the...
6
5882
by: RandomElle | last post by:
Hi there I'm hoping someone can help me out with the use of the Eval function. I am using Access2003 under WinXP Pro. I can successfully use the Eval function and get it to call any function with...
0
7192
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7064
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7445
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
1
4991
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4665
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3158
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3147
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1492
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
1
721
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.