By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,495 Members | 1,329 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,495 IT Pros & Developers. It's quick & easy.

Good C programming style

P: n/a
Hi!

I'm thinking about a good programming style, pros and cons of some
topics. Of course, this has nothing to do with indentation... Students
are now java-dependent (too bad) and I need some serious motivations
for many issues... I hope you can help me :) I begin with the two major
for now, others will come for sure!

- function variables: they're used to java, so no pointers. Personally
I'd use always pointers, but why could be better to use:
void myfun(int &i) or (int *i) or (int i)
given that the function can and cannot (the last case of course) modify
a parameter. I see performance issues (stack related)...

- defines: why they use function and variable defines? why they shouldn't?
#define MY_PI 3.1415
#define fun(x) ((x) * (x))
--
Sensei <se******@mac.com>

The difference between stupidity and genius is that genius has its
limits. (A. Einstein)

Nov 15 '05 #1
Share this Question
Share on Google+
43 Replies


P: n/a
"Sensei" <se******@tin.it> wrote in message
news:di**********@news.doit.wisc.edu...
Hi!

I'm thinking about a good programming style, pros and cons of some topics.
Of course, this has nothing to do with indentation... Students are now
java-dependent (too bad) and I need some serious motivations for many
issues...
So you're teaching C?
I hope you can help me :) I begin with the two major for now, others will
come for sure!

- function variables: they're used to java, so no pointers. Personally I'd
use always pointers, but why could be better to use:
void myfun(int &i)
but you don't appear able to distinguish C from C++
or (int *i) or (int i)
given that the function can and cannot (the last case of course) modify a
parameter. I see performance issues (stack related)...
and you don't appear to be aware of the consensus about
premature optimization

- defines: why they use function and variable defines? why they shouldn't?
#define MY_PI 3.1415
#define fun(x) ((x) * (x))
and you don't appear to be aware of the type-checking that a
real function can give, and that macros do not.

Running quickly in the other direction,
-Mike
Nov 15 '05 #2

P: n/a
Sensei wrote:
I'm thinking about a good programming style, pros and cons of some
topics. Of course, this has nothing to do with indentation... Students
are now java-dependent (too bad) and I need some serious motivations for
many issues... I hope you can help me :) I begin with the two major for
now, others will come for sure!
The questions you're asking are elemental. Read a good book on C and
these topics should be treated in some detail, along with explanations
that will help you decide on what is appropriate and why.
- function variables: they're used to java, so no pointers. Personally
I'd use always pointers, but why could be better to use:
void myfun(int &i) or (int *i) or (int i)
int &i is not C. You may be thinking of C++.

As for when to use pointers and when not, it's simple: pointers for
variable-sized data like strings, pointers also to implement
call-by-reference in C, that is, arguments you'll need to change.
Pointers also for structs, see below. And finally, pointers for
functions, since there's no other way to pass them.
given that the function can and cannot (the last case of course) modify
a parameter. I see performance issues (stack related)...
Mostly irrelevant. A C idiom is to always pass structure types by
pointer because passing most structures by value means copying, which is
indeed a waste of time in most cases, especially if the value isn't
modified. While a compiler could optimize this in some cases, it's not
expected to, and programmers don't count on it.
- defines: why they use function and variable defines? why they shouldn't?
#define MY_PI 3.1415
Established C practice is to use #define for constants since C is a bit
puzzling when it comes to constants. Declaring a variable "const" does
not make its value a constant expression for purposes of array sizes,
for example. Also, memory is allocated for const variables (great
oxymoron, incidentally :-) when it typically isn't necessary.

There's no such thing as a "function" or "variable" define, however.
Macros just establish textual replacement rules.
#define fun(x) ((x) * (x))

Use functions when you can, macros when you have to. The example above
is a case of when you don't have to.

As for when you need macros, that's not a matter of coding style.

S.
Nov 15 '05 #3

P: n/a
Sensei <se******@tin.it> writes:
I'm thinking about a good programming style, pros and cons of some
topics. Of course, this has nothing to do with indentation... Students
are now java-dependent (too bad) and I need some serious motivations
for many issues... I hope you can help me :) I begin with the two
major for now, others will come for sure!

- function variables: they're used to java, so no pointers. Personally
I'd use always pointers, but why could be better to use:
void myfun(int &i) or (int *i) or (int i)
given that the function can and cannot (the last case of course)
modify a parameter. I see performance issues (stack related)...
The term "function variables" is misleading; you mean parameters (the
things declared between the parentheses in a function declaration) or
arguments (the actual values passed in a function call).

The declaration "void myfun(int &i)" is not valid C. (I think it's
C++; see comp.lang.c++.)

The choice between "void myfun(int *p)" and "void myfun(int i)" isn't
really a matter of style; it's just a matter of what the function
needs to do. (Note that I've changed the name of the pointer
parameter; calling a pointer "i" is misleading.) If myfun needs to
change the value of an object specified by the caller, or if you want
to point to an array of integers, use a pointer. If you just want to
pass an integer value, use an int.

Note that if myfun's parameter is a pointer, you can only pass the
address of an ojbect (or a null pointer); you can't pass 42 or x+3.

If the parameter is of a struct type, it often makes sense to pass a
pointer even if you don't want to modify the struct object. Passing
an argument means making a copy of the argument and storing it in the
parameter; for large structures, this can be significantly expensive.
This consideration doesn't apply to ints, since there's no significant
performance difference between passing a copy of an int and passing a
copy of its address.
- defines: why they use function and variable defines? why they shouldn't?
#define MY_PI 3.1415
#define fun(x) ((x) * (x))


For MY_PI (BTW, everybody else's PI is closer to 3.1416), C doesn't
provide a mechanism for defining a constant floating-point value. You
can declare
const double my_pi = 3.14159265358979323848264;
but that creates a write-only variable, not a real constant. Macros
are useful for this kind of thing.

As for function-like macros, they're sometimes the best way to create
inline functions. (C99 has inline functions, but not all compilers
support them.) There are also things you can do in a macro that you
can't easily do in a function, such as using a type name as an
argument. But try not to be too tricky. Macros can be dangerous,
since they're expanded in a very early stage of compilation. They can
*look* like function calls or variable declarations, but they don't
necessarily act like them; for example, they pay no attention to
scope.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #4

P: n/a
Keith Thompson wrote:
<snip>
You can declare
const double my_pi = 3.14159265358979323848264;
but that creates a write-only variable, not a real constant. Macros
are useful for this kind of thing.

You know, a write-only variable is about the only thing C's missing. :-D

S.
Nov 15 '05 #5

P: n/a
Sensei wrote:
Hi!

I'm thinking about a good programming style, pros and cons of some
topics. Of course, this has nothing to do with indentation... Students
are now java-dependent (too bad) and I need some serious motivations for
many issues... I hope you can help me :) I begin with the two major for
now, others will come for sure!

- function variables: they're used to java, so no pointers. Personally
I'd use always pointers, but why could be better to use:
void myfun(int &i) or (int *i) or (int i)
void myfun(int &i) is an error in C. The two options that are C that you
list are
void myfun(int *i)
void myfun(int i)
given that the function can and cannot (the last case of course) modify
a parameter. I see performance issues (stack related)...
C does not require a stack, but assuming a stack implementation in
either case something will be pushed on to it, either the value of an
int or a pointer to an int. Do you *really* think either will have a
significant performance difference?

Write what you mean, don't try to micro-optimise.
- defines: why they use function and variable defines? why they shouldn't?
#define MY_PI 3.1415
How else would you define MY_PI? Apart from more accurately, that is ;-)
#define fun(x) ((x) * (x))


In this instance fun will work on any arithmetic type which can
sometimes be an advantage. I would generally recommend using functions
rather than function like macros *except* where you have a specific
reason to need a function like macro (e.g. if you wanted fun above to
operate on any arithmetic type and not have it convert everything to
double or long double).

Macro's can have unexpected effects such as given the above definition
if you do
fun(a++)
you actually invoke undefined behaviour because it will expand to
((a++) * (a++))
which attempts to modify a twice without an intervening sequence point.
This is why you should not use function like macros except where you
need them. It is also why you should follow the convention of spelling
macros in UPPER CASE to give people an immediate warning.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Nov 15 '05 #6

P: n/a
Skarmander wrote:
Keith Thompson wrote:
<snip>
You can declare
const double my_pi = 3.14159265358979323848264;
but that creates a write-only variable, not a real constant. Macros
are useful for this kind of thing.

You know, a write-only variable is about the only thing C's missing. :-D

S.


The write-only characteristic is priceless. In a former life I designed
a ram-disk subsystem, memory which should 'look' like a disk drive.
Until I got it working, I referred to it as write-only memory.

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 15 '05 #7

P: n/a

Sensei wrote:
Hi!

I'm thinking about a good programming style, pros and cons of some
topics. Of course, this has nothing to do with indentation... Students
are now java-dependent (too bad) and I need some serious motivations
for many issues... I hope you can help me :) I begin with the two major
for now, others will come for sure!

- function variables: they're used to java, so no pointers. Personally
I'd use always pointers, but why could be better to use:
void myfun(int &i) or (int *i) or (int i)
int &i is not standard C.
given that the function can and cannot (the last case of course) modify
a parameter. I see performance issues (stack related)...

- defines: why they use function and variable defines? why they shouldn't?
#define MY_PI 3.1415
You might want to extend pi a few more decimal places. The SUSv3
standard has a macro M_PI in <math.h>, but it isn't ISO-99 C.
#define fun(x) ((x) * (x))
This is considered bad style for a macro because the macro argument is
evaluated twice. Imagine what would happen if the argument to the macro
contained an increment or decrement operator.

Gregory Pietsch


--
Sensei <se******@mac.com>

The difference between stupidity and genius is that genius has its
limits. (A. Einstein)


Nov 15 '05 #8

P: n/a
Joe Wright wrote:
Skarmander wrote:
Keith Thompson wrote:
<snip>
You can declare
const double my_pi = 3.14159265358979323848264;
but that creates a write-only variable, not a real constant. Macros
are useful for this kind of thing.

You know, a write-only variable is about the only thing C's missing. :-D


The write-only characteristic is priceless. In a former life I designed
a ram-disk subsystem, memory which should 'look' like a disk drive.
Until I got it working, I referred to it as write-only memory.

I have actually worked on machines that had write-only memory, typically
memory-mapped hardware (the addresses corresponding to "out" ports of
some sort, of course). Aside from the curiousity value, it's really not
that different from regular memory -- you won't use it to store
temporaries or read back what you've written, after all.

S.
Nov 15 '05 #9

P: n/a
Keith Thompson wrote:
const double my_pi = 3.14159265358979323848264;


Where the hell did you get the idea that the next digit after
3.1415926535897932384 was 8?!!!

;)

--
pete
Nov 15 '05 #10

P: n/a
pete <pf*****@mindspring.com> writes:
Keith Thompson wrote:
const double my_pi = 3.14159265358979323848264;


Where the hell did you get the idea that the next digit after
3.1415926535897932384 was 8?!!!

;)


Oops, I meant 6 of course.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #11

P: n/a
Keith Thompson wrote:

pete <pf*****@mindspring.com> writes:
Keith Thompson wrote:
const double my_pi = 3.14159265358979323848264;


Where the hell did you get the idea that the next digit after
3.1415926535897932384 was 8?!!!

;)


Oops, I meant 6 of course.


I've waited over two years for a chance to use that line again.

http://groups.google.com/group/comp....5e5b2a7f8e39ab

Thank you.

--
pete
Nov 15 '05 #12

P: n/a
Gregory Pietsch said:
Sensei wrote:
#define MY_PI 3.1415


You might want to extend pi a few more decimal places.


Why? Observe:

Circumference of Earth (plus or minus a bit): 40000000 metres.
Pi = 3.1415
Radius of Earth: 6366385 metres

Let's add 1 dp.

Circumference of Earth (plus or minus a bit): 40000000 metres.
Pi = 3.14159
Radius of Earth: 6366203 metres

Difference from last result: 182 metres. If you're calculating fuel
requirements for a trip round the entire planet, you'd factor in a
contingency anyway; you're not going to crash for the sake of 182 metres.

Let's add another.

Circumference of Earth (plus or minus a bit): 40000000 metres.
Pi = 3.141592
Radius of Earth: 6366199 metres

Difference from last result: 4 metres. Good enough for nuclear war.

Let's add another.

Circumference of Earth (plus or minus a bit): 40000000 metres.
Pi = 3.1415926 (still comfortably within the ability of a pocket calculator)
Radius of Earth: 6366198 metres. Difference from last result: 1 metre. Good
enough for assassinating one mad dictator (or one troublesome priest) from
the other side of the planet.

Let's add another.

Circumference of Earth (plus or minus a bit): 40000000 metres.
Pi = 3.14159265
Radius of Earth: 6366198 metres. Difference from last result: 0 metres.
(Okay, so I'm rounding - but the difference is less than 1 metre, that's
the point.)

So who gives a stuff? :-)
--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/2005
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Nov 15 '05 #13

P: n/a
pete <pf*****@mindspring.com> writes:
Keith Thompson wrote:
pete <pf*****@mindspring.com> writes:
> Keith Thompson wrote:
>> const double my_pi = 3.14159265358979323848264;
>
> Where the hell did you get the idea that the next digit after
> 3.1415926535897932384 was 8?!!!
>
> ;)


Oops, I meant 6 of course.


I've waited over two years for a chance to use that line again.

http://groups.google.com/group/comp....5e5b2a7f8e39ab

Thank you.


You're welcome. Had I known, I might have made the mistake
intentionally. 8-)}

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #14

P: n/a
On 2005-10-07 21:28:50 +0200, "Mike Wahler" <mk******@mkwahler.net> said:
"Sensei" <se******@tin.it> wrote in message
news:di**********@news.doit.wisc.edu...
Hi!

I'm thinking about a good programming style, pros and cons of some
topics. Of course, this has nothing to do with indentation... Students
are now java-dependent (too bad) and I need some serious motivations
for many issues...
So you're teaching C?

Nope. I'm an engineer working on theoretics. I *have* to teach C, and
I'm studying before doing anything wrong.

but you don't appear able to distinguish C from C++

Correct. I'm trying.


and you don't appear to be aware of the consensus about
premature optimization

My biggest programming efforts have always been on assembly. I'm used
to do a shift instead of dividing or multiplying by 2. I've read it's
not useful on high level languages like C.

If a variable is passed on the stack, I imagine *i pushes an address,
while i pushed the entire data, so if i is a big structure is not a
nice thing.

Moreover, I don't know if C says *how* parameters are passed to
functions: stack, pointer, whatever...


- defines: why they use function and variable defines? why they shouldn't?
#define MY_PI 3.1415
#define fun(x) ((x) * (x))


and you don't appear to be aware of the type-checking that a
real function can give, and that macros do not.

Of course macros are macros. No checks, no functions. Why using one
instead of another is not clear to me. As I said, I'm an assembly guy,
and ``functions'' do not really exist.

You don't appear to understand that people could ask for informations
here about std-c with different knowledge :)
--
Sensei <se******@mac.com>

The difference between stupidity and genius is that genius has its
limits. (A. Einstein)

Nov 15 '05 #15

P: n/a
On 2005-10-07 21:35:26 +0200, Skarmander <in*****@dontmailme.com> said:
Sensei wrote:
I'm thinking about a good programming style, pros and cons of some
topics. Of course, this has nothing to do with indentation... Students
are now java-dependent (too bad) and I need some serious motivations
for many issues... I hope you can help me :) I begin with the two major
for now, others will come for sure!
The questions you're asking are elemental. Read a good book on C and
these topics should be treated in some detail, along with explanations
that will help you decide on what is appropriate and why.

As I said in another post, I'm studying now.
given that the function can and cannot (the last case of course) modify
a parameter. I see performance issues (stack related)...
Mostly irrelevant. A C idiom is to always pass structure types by
pointer because passing most structures by value means copying, which
is indeed a waste of time in most cases, especially if the value isn't
modified. While a compiler could optimize this in some cases, it's not
expected to, and programmers don't count on it.

Clear.

- defines: why they use function and variable defines? why they shouldn't?
#define MY_PI 3.1415
Established C practice is to use #define for constants since C is a bit
puzzling when it comes to constants. Declaring a variable "const" does
not make its value a constant expression for purposes of array sizes,
for example. Also, memory is allocated for const variables (great
oxymoron, incidentally :-) when it typically isn't necessary.

There's no such thing as a "function" or "variable" define, however.
Macros just establish textual replacement rules.

Yes but...
#define fun(x) ((x) * (x))

Use functions when you can, macros when you have to. The example above
is a case of when you don't have to.

As for when you need macros, that's not a matter of coding style.


....this is puzzling to me. I've seen functions replaced by macros, like this:

#define xge_mklink_slot(com,from,to,slotfrom,slotto) \
{\
tkey _slotfrom=(slotfrom);\
tkey _slotto =(slotto );\
\
CHECKPOINT("ie",getcell((com),(from)).level!=0xff &&
getcell((com),(to)).level!=0xff);\
\
if (!_slotfrom)\
{\
if (!(com)->memlink.freelist) realloc_link((com));\
_slotfrom=(com)->memlink.freelist;\
(com)->memlink.freelist=getlink((com),_slotfrom).next; \
++((com)->memlink.num);\
\
if (!getcell((com),(from)).nup)\
getcell((com),(from)).firstup=_slotfrom;\
else\

getlink((com),getcell((com),(from)).lastup).next=_ slotfrom;\
\
getlink((com),_slotfrom).next=0;\
getlink((com),_slotfrom).prev=getcell((com),(from) ).lastup; \
getcell((com),(from)).lastup=_slotfrom;\
++getcell((com),(from)).nup;\
}\
\
if (!_slotto)\
............
So, I was wondering why and when it's a good idea to use defines.
--
Sensei <se******@mac.com>

The difference between stupidity and genius is that genius has its
limits. (A. Einstein)

Nov 15 '05 #16

P: n/a
On 2005-10-07 21:42:37 +0200, Keith Thompson <ks***@mib.org> said:

As for function-like macros, they're sometimes the best way to create
inline functions. (C99 has inline functions, but not all compilers
support them.) There are also things you can do in a macro that you
can't easily do in a function, such as using a type name as an
argument. But try not to be too tricky. Macros can be dangerous,
since they're expanded in a very early stage of compilation. They can
*look* like function calls or variable declarations, but they don't
necessarily act like them; for example, they pay no attention to scope.

Ok, so defines are used to improve performances as inline functions are
not supported everywhere.
--
Sensei <se******@mac.com>

The difference between stupidity and genius is that genius has its
limits. (A. Einstein)

Nov 15 '05 #17

P: n/a
Sensei wrote:
On 2005-10-07 21:28:50 +0200, "Mike Wahler" <mk******@mkwahler.net> said:
"Sensei" <se******@tin.it> wrote in message
news:di**********@news.doit.wisc.edu...
Hi!

I'm thinking about a good programming style, pros and cons of some
topics. Of course, this has nothing to do with indentation...
Students are now java-dependent (too bad) and I need some serious
motivations for many issues...
So you're teaching C?


Nope. I'm an engineer working on theoretics. I *have* to teach C, and
I'm studying before doing anything wrong.


Well, I hope you have plenty of time, since you have a *lot* to learn.
but you don't appear able to distinguish C from C++


Correct. I'm trying.


Try to learn one language at a time. Trying to learn two, especially two
with a lot of similarities, is bound to lead to confusion.
and you don't appear to be aware of the consensus about
premature optimization


My biggest programming efforts have always been on assembly. I'm used to
do a shift instead of dividing or multiplying by 2. I've read it's not
useful on high level languages like C.


What you have read is correct. Modern compilers have an optimiser to do
this for you.
If a variable is passed on the stack, I imagine *i pushes an address,
while i pushed the entire data, so if i is a big structure is not a nice
thing.
Yes, that is correct. With a large structure you would tend to pass a
pointer to avoid copying a lot of data.
Moreover, I don't know if C says *how* parameters are passed to
functions: stack, pointer, whatever...
C does not specify a stack. All it specifies is that parameters are
passed by value (even pointers). On at least some systems parameters
will be passed in registers.
- defines: why they use function and variable defines? why they
shouldn't?
#define MY_PI 3.1415
#define fun(x) ((x) * (x))


and you don't appear to be aware of the type-checking that a
real function can give, and that macros do not.


Of course macros are macros. No checks, no functions. Why using one
instead of another is not clear to me. As I said, I'm an assembly guy,
and ``functions'' do not really exist.


Type checking is a wonderful thing, it allows the compiler to complain
if you do something obviously stupid. Such as passing a pointer to a
function requiring an integer.
You don't appear to understand that people could ask for informations
here about std-c with different knowledge :)


We are quite used to that.

I strongly suggest you work through K&R2 and read the FAQ for this group
(which will explain what K&R2 is).

Also remember that high level languages were invented to make
programming easier, and this means you should forget about using a lot
of the little tricks you use as an assembler programmer.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Nov 15 '05 #18

P: n/a
Sensei wrote:
So, I was wondering why and when it's a good idea to use defines.


If a #define can make the source code easier to read,
then that is why and when.

--
pete
Nov 15 '05 #19

P: n/a
Sensei wrote:
On 2005-10-07 21:35:26 +0200, Skarmander <in*****@dontmailme.com> said:
Sensei wrote:
<snip>
#define fun(x) ((x) * (x))
Use functions when you can, macros when you have to. The example above
is a case of when you don't have to.

As for when you need macros, that's not a matter of coding style.

...this is puzzling to me. I've seen functions replaced by macros, like
this:

#define xge_mklink_slot(com,from,to,slotfrom,slotto) \
{\
tkey _slotfrom=(slotfrom);\
tkey _slotto =(slotto );\
\
CHECKPOINT("ie",getcell((com),(from)).level!=0xff &&
getcell((com),(to)).level!=0xff);\
\
if (!_slotfrom)\
{\
if (!(com)->memlink.freelist) realloc_link((com));\
_slotfrom=(com)->memlink.freelist;\
(com)->memlink.freelist=getlink((com),_slotfrom).next; \
++((com)->memlink.num);\
\
if (!getcell((com),(from)).nup)\
getcell((com),(from)).firstup=_slotfrom;\
else\

getlink((com),getcell((com),(from)).lastup).next=_ slotfrom;\
\
getlink((com),_slotfrom).next=0;\

getlink((com),_slotfrom).prev=getcell((com),(from) ).lastup; \
getcell((com),(from)).lastup=_slotfrom;\
++getcell((com),(from)).nup;\
}\
\
if (!_slotto)\
...........
This is absolutely horrible. Words fail me. Whoever wrote this should be
shot.

Let's go over why this is a bad idea:

- In a macro, arguments are not checked against their types, as there
are no types. This means that the function is both harder to call ("com"
must be a pointer, but of what type?) and the compiler can offer less
help checking validity.

- Generalizing, the validity of a macro simply cannot be checked on its
own. Only uses of it can be checked. Errors or warnings that occur from
such a use could be either due to bad use or a bad macro, and it'll be
hard to tell which is which.

- Unlike functions, macros use textual replacement for their arguments.
If an argument uses a side-effect (it modifies the program state when
evaluated) then you typically cannot use it. For example:
xge_mklink_slot(c, f++, t++, slf, slt);
This does not have the same effect as the equivalent function call
would: every time "from" is replaced in the macro it is replaced with
"f++". That is, f will be incremented every time "from" is used!

- This is very likely to *harm* performance. Yes, you read that right.
If this macro is invoked multiple times, the great big block of code it
stands for is inserted *every time*. Do this a few times and you'll get
code that is huge. And WHY? Function calls are not nearly as expensive
as most people like to pretend. It is in fact likely this code will run
slower because big code means the instruction cache most modern
processors are equipped with cannot be effectively used. Never try to
outsmart the compiler. Only educate it in things you know it cannot see.
Making decisions on when to inline functions is something a compiler is
qualified to do, and only code profiling should be admissible evidence
to the contrary.

Apropos inlining: almost all compilers I know offer a way to indicate
that inlining is desirable (or even force it where possible). The new
C99 standard adds an "inline" keyword, and most pre-C99 compilers
support an "inline", "_inline", "__inline" keyword or some variation
thereof. Macros are almost never necessary or desirable to get an
inlined function.

All that said, there is one purpose this macro could still serve that
cannot be achieved otherwise in C: precisely because the arguments have
no types, it can be used as a template to produce similar functions that
differ only in the type of the arguments. This is what templates
accomplish in C++ and generics accomplish in the most recent versions of
Java.

But even so, it should only be used in a way that does not compromise
type safety, by defining the type-safe functions:

/* Unlike XGE_MKLINK_SLOT, the compiler will warn or stop if the
argument types do not match the formal parameter types. */
[return-type] xge_mklink_slot(xge_com* com, xge_cell from, xge_cell to,
tkey slotfrom, tkey slotto) {
return XGE_MKLINK_SLOT(com, from, to, slotfrom, slotto);
}

Here [return-type] I cannot know, and the xge_com and xge_cell types are
invented by me. I capitalized XGE_MKLINK_SLOT because macro names
*should* be capitalized to prevent confusion: as I've said, using a
macro is not the same thing as calling a function, and it's dangerous to
pretend that it is.

Even this technique is dubious because xge_mklink_slot is a highly
specific macro, and it's unlikely it's used in the way I sketched above.
Note also that in C, generic functions are usually written by passing
around generic pointers. Consult your C book for more information; it
will probably mention the qsort() function as an example.

This macro *should* be rewritten to a function. I cannot conceive of any
reason why a macro would be preferrable in this case. Do you understand
why I said it's not a matter of coding style? It's a matter of what you
want to achieve, not how it looks. "Style", if it comes into play at
all, is to prefer functions to macros consistently, and being ready to
justify your use of a macro.
So, I was wondering why and when it's a good idea to use defines.

Don't think in terms of "good idea/bad idea". Learn what purpose and
what drawbacks each feature has, then apply this knowledge in every case
to achieve the best result. In case of macros, the drawbacks associated
with them very often outweigh the benefits, especially when it comes to
replacing functions.

I can give you the short version, of course, but keep in mind that these
are only rules of thumb and not absolute commandments. Use a macro for:

- defining symbolic constants that are not part of an enumerated type.
Example: #define M_PI 3.1415926536
- encapsulating system-specific constructs that cannot be abstracted by
a function. Example: #define INLINE __inline
- allowing header files to be included more than once without error.
Example:
#ifndef HEADER_H
#define HEADER_H
...contents of "header.h"
#endif

These are the basic established "good ideas" for macros. There are other
circumstances in which experienced C programmers will use macros, but
you should leave them until you can understand why. I won't attempt to
explain it all in a Usenet post; consult the books written by people
who've had more time than me to think about it.

S.
Nov 15 '05 #20

P: n/a
Skarmander wrote:
Sensei wrote:
On 2005-10-07 21:35:26 +0200, Skarmander <in*****@dontmailme.com> said:
<snip> #define xge_mklink_slot(com,from,to,slotfrom,slotto) \
{\
<snip> But even so, it should only be used in a way that does not compromise
type safety, by defining the type-safe functions:

/* Unlike XGE_MKLINK_SLOT, the compiler will warn or stop if the
argument types do not match the formal parameter types. */
[return-type] xge_mklink_slot(xge_com* com, xge_cell from, xge_cell to,
tkey slotfrom, tkey slotto) {
return XGE_MKLINK_SLOT(com, from, to, slotfrom, slotto);
}

This can't possibly be right because xge_mklink_slot is defined in such
a way that it cannot evaluate to an expression. Should be

[return-type] xge_mklink_slot(xge_com* com, xge_cell from, xge_cell to,
tkey slotfrom, tkey slotto) {
XGE_MKLINK_SLOT(com, from, to, slotfrom, slotto);
}

It's likely that XGE_MKLINK_SLOT contains no return statement at all,
and [return-type] is just "void".

Left as an exercise to the reader: why could this otherwise produce
warnings of unreachable code, and how should we fix this? Just another
example of why macros should be used carefully. :-)

S.
Nov 15 '05 #21

P: n/a
On 2005-10-08 12:45:05 +0200, Flash Gordon <sp**@flash-gordon.me.uk> said:

What you have read is correct. Modern compilers have an optimiser to do
this for you.

Most welcome!

C does not specify a stack. All it specifies is that parameters are
passed by value (even pointers). On at least some systems parameters
will be passed in registers.

Quite understandable.

Type checking is a wonderful thing, it allows the compiler to complain
if you do something obviously stupid. Such as passing a pointer to a
function requiring an integer.

Yep. True.

You don't appear to understand that people could ask for informations
here about std-c with different knowledge :)
We are quite used to that.

I strongly suggest you work through K&R2 and read the FAQ for this
group (which will explain what K&R2 is).

I'm already reading them :)

Also remember that high level languages were invented to make
programming easier, and this means you should forget about using a lot
of the little tricks you use as an assembler programmer.

Ok.

--
Sensei <se******@mac.com>

The difference between stupidity and genius is that genius has its
limits. (A. Einstein)

Nov 15 '05 #22

P: n/a
On 2005-10-08 13:26:29 +0200, Skarmander <in*****@dontmailme.com> said:
Left as an exercise to the reader: why could this otherwise produce
warnings of unreachable code, and how should we fix this? Just another
example of why macros should be used carefully. :-)

Thanks. I've read your post(s) and I find them very useful.

I have to learn :)

--
Sensei <se******@mac.com>

The difference between stupidity and genius is that genius has its
limits. (A. Einstein)

Nov 15 '05 #23

P: n/a
Sensei wrote:
On 2005-10-07 21:42:37 +0200, Keith Thompson <ks***@mib.org> said:

As for function-like macros, they're sometimes the best way to create
inline functions. (C99 has inline functions, but not all compilers
support them.) There are also things you can do in a macro that you
can't easily do in a function, such as using a type name as an
argument.
.... Ok, so defines are used to improve performances as inline functions are
not supported everywhere.


Yes, sometimes to a ridiculous degree. On the other hand, for embedded
systems simple function-like macros that have constant arguments can
generate very optimized code, due to the ability of the compiler to
evaluate the constant expressions at compile time.

Another use I make of function-like macros is for debugging. The
standard assert() macro is an example. Define NDEBUG and no code is
generated for the macro. I extend this concept for driving realtime
test points for embedded applications. In my case if the test pin macro
(separate from the function-like debug macro) is not defined, no code is
generated.

Thad

Nov 15 '05 #24

P: n/a
In article <di**********@news.doit.wisc.edu>, Sensei <se******@tin.it>
writes
Hi!

I'm thinking about a good programming style, pros and cons of some
topics. Of course, this has nothing to do with indentation... Students
are now java-dependent (too bad) and I need some serious motivations
for many issues... I hope you can help me :) I begin with the two major
for now, others will come for sure!

- function variables: they're used to java, so no pointers. Personally
I'd use always pointers, but why could be better to use:
void myfun(int &i) or (int *i) or (int i)
given that the function can and cannot (the last case of course) modify
a parameter. I see performance issues (stack related)...

- defines: why they use function and variable defines? why they shouldn't?
#define MY_PI 3.1415
#define fun(x) ((x) * (x))


Try MISRA-C

www.misra-c.com

It is the automotive (and now general embedded and safety critical)
coding guideline

--
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
\/\/\/\/\ Chris Hills Staffs England /\/\/\/\/
/\/\/ ch***@phaedsys.org www.phaedsys.org \/\/\
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/

Nov 15 '05 #25

P: n/a
On Sat, 8 Oct 2005 09:20:17 +0000 (UTC), in comp.lang.c , Richard
Heathfield <in*****@invalid.invalid> wrote:
Gregory Pietsch said:
Sensei wrote:
#define MY_PI 3.1415


You might want to extend pi a few more decimal places.


Why? Observe:


(calculation showing differences in radius of earth)

On the other hand, if you're trying to fit a piston into a cylinder,
such wild inaccuracies can matter. Either it will seize in use or will
be so slack as to be useless. This might be quite important if it were
say the pump for an artificial heart or the drive piston of a swing
bridge.
--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>

----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Nov 15 '05 #26

P: n/a
Mark McIntyre <ma**********@spamcop.net> writes:
On Sat, 8 Oct 2005 09:20:17 +0000 (UTC), in comp.lang.c , Richard
Heathfield <in*****@invalid.invalid> wrote:
Gregory Pietsch said:
Sensei wrote:

#define MY_PI 3.1415

You might want to extend pi a few more decimal places.


Why? Observe:


(calculation showing differences in radius of earth)

On the other hand, if you're trying to fit a piston into a cylinder,
such wild inaccuracies can matter. Either it will seize in use or will
be so slack as to be useless. This might be quite important if it were
say the pump for an artificial heart or the drive piston of a swing
bridge.


And if I have a definition of PI that uses the full precision of
whatever type you're going to use (in this case, you should probably
define it with an "L" suffix and use at least as many digits as long
double supports), I don't have to *think* about whether it's good
enough. 3.1415 (or 3.1416) might be good enough for some
applications. 3.141592653589793238462643383279502884197169399375 106L
is good enough for anything you can do with long doubles (assuming
long double is no more than 50 or so digits). And you only have to
define it once.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #27

P: n/a
In article <di**********@news.doit.wisc.edu> Sensei <se******@tin.it> wrote:
Ok, so [#]defines [of function-like macros] are used to improve
performances as inline functions are not supported everywhere.


Or, sometimes, inline macros and/or functions are used to make
performance *worse*.

As a case in point, the BSD code that went into NetBSD performs
all file-system operations through what look like remote procedure
call (RPC) mechanisms, even when doing local procedure calls [%]:

#define VOP_READ(vp, uio, ioflag, cred) \
(GCC-specific code, omitted)
/* and so on for all the many vnode ops */

An RPC requires "marshalling" parameters into a data structure,
so the inline macro/function did something equivalent to:

args.desc = &vnode_read_desc;
args.vp = vp;
args.uio = uio;
args.ioflag = ioflag;
args.cred = cred;
/* find the function to call */
funcptr = inline_table_lookup(vp->filesysinfo, vnode_read_op);
return (*funcptr)(&args);

On the VAX, where this work was originally done in the 1990s,
expanding all the RPC code in-line sped things up, in part because
every subroutine call on the VAX took the equivalent of over a
dozen "regular" instruction times.

As an experiment, the NetBSD team tried "un-inlining" the code, so
that all the marshalling was in actual functions, instead of being
expanded in-line. On at least some, and I think most, of the
supported architectures, the result was a significantly smaller
*and faster* kernel.

[% I argued against this, back when Kirk McKusick was integrating
John Heidemann's changes, but I lost that argument.]
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 15 '05 #28

P: n/a
cs
On Sat, 8 Oct 2005 10:55:55 +0200, Sensei <se******@tin.it> wrote:
On 2005-10-07 21:35:26 +0200, Skarmander <in*****@dontmailme.com> said:
#define fun(x) ((x) * (x))


you can do something

fun(t++);

expanded in

(t++)*(t++);

??

#define xge_mklink_slot(com,from,to,slotfrom,slotto) \
{\
tkey _slotfrom=(slotfrom);\
tkey _slotto =(slotto );\
_name are reserved for compiler; i don't like thid kind of macro
So, I was wondering why and when it's a good idea to use defines.


for me it is not a good idea for debug puorpose and ... because it is
more easy to write errors

the only macros that i like are
#define P printf
#define F for
#defile W while
#define U unsigned
#define R return

but no one seems agree in this with me ...
Nov 15 '05 #29

P: n/a

"Keith Thompson" <ks***@mib.org> wrote

And if I have a definition of PI that uses the full precision of
whatever type you're going to use (in this case, you should probably
define it with an "L" suffix and use at least as many digits as long
double supports), I don't have to *think* about whether it's good
enough. 3.1415 (or 3.1416) might be good enough for some
applications. 3.141592653589793238462643383279502884197169399375 106L
is good enough for anything you can do with long doubles (assuming
long double is no more than 50 or so digits). And you only have to
define it once.

If you are working with graphics, it generally doesn't matter if the image
is a pixel out. However if one polygon is a pixel too low, and the adjacent
one a pixel too high, you get a hole, which does matter.
One way of checking whether your code is robust to this type of problem is
to deliberately degrade accuracy, for instance by using 3.142 for PI.
Nov 15 '05 #30

P: n/a
(Concerning the accuracy of pi)

With 42 digits of pi, you could find the circumference of the known
universe to within the width of a proton, but for practical matters, an
accuracy of one or two decimal places is ample.

LOL, Gregory Pietsch

Nov 15 '05 #31

P: n/a
Gregory Pietsch wrote:
(Concerning the accuracy of pi)

With 42 digits of pi, you could find the circumference of the known
universe to within the width of a proton, but for practical matters, an
accuracy of one or two decimal places is ample.


It all depends on what you are using PI for. The 1% or 0.1% error may
only be one error factor within the calculation, and it may be scaled up
by other things. I have certainly used PI in calculations where I have
also used other approximations (ones which actually saved a significant
amount of processing time). So if you are trying to reduce the error the
place to start is with the accuracy of the constants, because you can
improve those up to what your implementation can cope with without
impacting on other aspects of performance. Of course, a far easier
approach is to never introduce error in constants for the sake of a
little typing.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Nov 15 '05 #32

P: n/a
On 2005-10-09 21:34:29 +0200, cs <n@ss.g> said:

for me it is not a good idea for debug puorpose and ... because it is
more easy to write errors

the only macros that i like are
#define P printf
#define F for
#defile W while
#define U unsigned
#define R return

but no one seems agree in this with me ...

Ok. I see.

So why I see so often something like:

#define CEXCERPT do { \
some(); \
C_code(); \
here(); \
} while(0)

Is it just some person thinking he would achieve more speed?

--
Sensei <se******@mac.com>

The difference between stupidity and genius is that genius has its
limits. (A. Einstein)

Nov 15 '05 #33

P: n/a
Sensei wrote:
So why I see so often something like:

#define CEXCERPT do { \
some(); \
C_code(); \
here(); \
} while(0)

Is it just some person thinking he would achieve more speed?


No, it's some person arranging that their macro can be expanded
as
CEXCERPT;

without confusion. (I would have thought, even more likely
with a parameterised macro.)

--
Chris "electric hedgehog" Dollin
"I know three kinds: hot, cool, and what-time-does-the-tune-start?"
Nov 15 '05 #34

P: n/a
In article <di**********@malatesta.hpl.hp.com>,
Chris Dollin <ke**@hpl.hp.com> wrote:
#define CEXCERPT do { \
some(); \
C_code(); \
here(); \
} while(0)
No, it's some person arranging that their macro can be expanded
as
CEXCERPT;

without confusion.


In particular, as the body of an if. If the macro were defined as just
the bracketed part, then

if(test)
CEXCERPT;
else
...

would be an error, and

if(test1)
if(test2)
CEXCERPT;
else
...

would not behave as suggested by the indentation.

-- Richard

Nov 15 '05 #35

P: n/a
cs
On Mon, 10 Oct 2005 14:29:18 +0200, Sensei <se******@tin.it> wrote:
On 2005-10-09 21:34:29 +0200, cs <n@ss.g> said:

for me it is not a good idea for debug puorpose and ... because it is
more easy to write errors

the only macros that i like are
#define P printf
#define F for
#defile W while
#define U unsigned
#define R return

but no one seems agree in this with me ...

Ok. I see.

So why I see so often something like:

#define CEXCERPT do { \
some(); \
C_code(); \
here(); \
} while(0)

Is it just some person thinking he would achieve more speed?


it is a trick
because some people want a more than one instruction macro and
they want save a call (in some loop i think)
a=1;
CEXCERPT;
b=1;

is expanded in
a=1;
{ some(); C_code(); here(); } while(0);
b=1;

so in this way you can use ";" for end the instruction (CEXCERPT;)

note that in this way
if(a==rand()%9)
CEXCERPT;
else b=1;
is also ok
is expanded in

if(a==rand()%9)
{ some(); C_code(); here(); } while(0);
else b=1;

the same seem ok
if(a==rand()%9)
{ CEXCERPT; }
while(a==rand()%9)
CEXCERPT;
while(a==rand()%9)
{ CEXCERPT; }
etc
Nov 15 '05 #36

P: n/a
cs
On Mon, 10 Oct 2005 17:16:33 +0200, cs <n@ss.g> wrote:
On Mon, 10 Oct 2005 14:29:18 +0200, Sensei <se******@tin.it> wrote:
On 2005-10-09 21:34:29 +0200, cs <n@ss.g> said:

for me it is not a good idea for debug puorpose and ... because it is
more easy to write errors

the only macros that i like are
#define P printf
#define F for
#defile W while
#define U unsigned
#define R return

but no one seems agree in this with me ...

Ok. I see.

So why I see so often something like:

#define CEXCERPT do { \
some(); \
C_code(); \
here(); \
} while(0)

Is it just some person thinking he would achieve more speed?


it is a trick
because some people want a more than one instruction macro and
they want save a call (in some loop i think)
a=1;
CEXCERPT;
b=1;


i would like to say this
is expanded in
a=1; do { some(); C_code(); here(); } while(0);b=1;

so in this way you can use ";" for end the instruction (CEXCERPT;)

note that in this way
if(a==rand()%9)
CEXCERPT;
else b=1;
is also ok
is expanded in

if(a==rand()%9) do { some(); C_code(); here(); } while(0);else b=1;

the same seem ok
if(a==rand()%9)
{ CEXCERPT; }
while(a==rand()%9)
CEXCERPT;
while(a==rand()%9)
{ CEXCERPT; }
etc

Nov 15 '05 #37

P: n/a
On 2005-10-10 15:31:40 +0200, Chris Dollin <ke**@hpl.hp.com> said:
Sensei wrote:
So why I see so often something like:

#define CEXCERPT do { \
some(); \
C_code(); \
here(); \
} while(0)

Is it just some person thinking he would achieve more speed?


No, it's some person arranging that their macro can be expanded
as CEXCERPT;

without confusion. (I would have thought, even more likely
with a parameterised macro.)

I understood why he does not use a ; at the end, but why someone would
have such a big macro... is beyond my knowledge, something like the
xge_whatever stuff I found... :)

--
Sensei <se******@mac.com>

The difference between stupidity and genius is that genius has its
limits. (A. Einstein)

Nov 15 '05 #38

P: n/a
Sensei <se******@tin.it> writes:
On 2005-10-10 15:31:40 +0200, Chris Dollin <ke**@hpl.hp.com> said:
Sensei wrote:
So why I see so often something like:
#define CEXCERPT do { \
some(); \
C_code(); \
here(); \
} while(0)
Is it just some person thinking he would achieve more speed?

No, it's some person arranging that their macro can be expanded
as CEXCERPT;
without confusion. (I would have thought, even more likely
with a parameterised macro.)


I understood why he does not use a ; at the end, but why someone would
have such a big macro... is beyond my knowledge, something like the
xge_whatever stuff I found... :)


One reason to do this is to save the overhead of a function call.
That's rarely worth the effort, though it can be if it's likely to be
invoked repeatedly in a loop. For example, putc() in <stdio.h> is
commonly implemented as a complex macro; likewise for the is*() and
to*() functions/macros in <ctype.h>.

Another reason is to do something that you can't do with a function,
even an inline one. For example, a function argument can only be an
expression; a macro argument can be a type name. The offsetof() macro
is an example that can't be implemented as a function.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #39

P: n/a
Sensei wrote:
On 2005-10-10 15:31:40 +0200, Chris Dollin <ke**@hpl.hp.com> said:
Sensei wrote:
So why I see so often something like:

#define CEXCERPT do { \
some(); \
C_code(); \
here(); \
} while(0)

Is it just some person thinking he would achieve more speed?


No, it's some person arranging that their macro can be expanded
as CEXCERPT;

without confusion. (I would have thought, even more likely
with a parameterised macro.)

I understood why he does not use a ; at the end, but why someone would
have such a big macro... is beyond my knowledge, something like the
xge_whatever stuff I found... :)


How big is "big"?

#define NEEDS(mill, n) \
do { \
if (vm->myHeap->available < (Size) (n)) \
(FREEZE(), millRegenerate( mill ), MELT()); \
} while (0)

--
Chris "electric hedgehog" Dollin
"I know three kinds: hot, cool, and what-time-does-the-tune-start?"
Nov 15 '05 #40

P: n/a
Chris Dollin wrote:
Sensei wrote:

On 2005-10-10 15:31:40 +0200, Chris Dollin <ke**@hpl.hp.com> said:

Sensei wrote:
So why I see so often something like:

#define CEXCERPT do { \
some(); \
C_code(); \
here(); \
} while(0)

Is it just some person thinking he would achieve more speed?

No, it's some person arranging that their macro can be expanded
as CEXCERPT;

without confusion. (I would have thought, even more likely
with a parameterised macro.)

I understood why he does not use a ; at the end, but why someone would
have such a big macro... is beyond my knowledge, something like the
xge_whatever stuff I found... :)

How big is "big"?

#define NEEDS(mill, n) \
do { \
if (vm->myHeap->available < (Size) (n)) \
(FREEZE(), millRegenerate( mill ), MELT()); \
} while (0)

#define INLINE inline

INLINE void needs(? mill, Size n) {
if (vm -> myHeap -> available < n) {
freeze();
millRegenerate(mill);
melt();
}
}

S.
Nov 15 '05 #41

P: n/a
Skarmander wrote:
Chris Dollin wrote:
Sensei wrote:

On 2005-10-10 15:31:40 +0200, Chris Dollin <ke**@hpl.hp.com> said:
Sensei wrote:
>So why I see so often something like:
>
>#define CEXCERPT do { \
>some(); \
>C_code(); \
>here(); \
>} while(0)
>
>Is it just some person thinking he would achieve more speed?

No, it's some person arranging that their macro can be expanded
as CEXCERPT;

without confusion. (I would have thought, even more likely
with a parameterised macro.)
I understood why he does not use a ; at the end, but why someone would
have such a big macro... is beyond my knowledge, something like the
xge_whatever stuff I found... :)

How big is "big"?

#define NEEDS(mill, n) \
do { \
if (vm->myHeap->available < (Size) (n)) \
(FREEZE(), millRegenerate( mill ), MELT()); \
} while (0)

#define INLINE inline

INLINE void needs(? mill, Size n) {
if (vm -> myHeap -> available < n) {
freeze();
millRegenerate(mill);
melt();
}
}


Won't work.

FREEZE() is a macro, MELT is a macro, both of them use variables
available where NEEDS is called - such as, for example, `vm`.

And `inline` wasn't routinely available when this code was written;
furthermore, failure to inline is likely to make the code run
significantly more slowly. Since this is part of the system core,
it would matter.

--
Chris "electric hedgehog" Dollin
"I know three kinds: hot, cool, and what-time-does-the-tune-start?"
Nov 15 '05 #42

P: n/a
Chris Dollin wrote:
Skarmander wrote:

Chris Dollin wrote:
Sensei wrote:
<snip>I understood why he does not use a ; at the end, but why someone would
have such a big macro... is beyond my knowledge, something like the
xge_whatever stuff I found... :)
How big is "big"?

#define NEEDS(mill, n) \
do { \
if (vm->myHeap->available < (Size) (n)) \
(FREEZE(), millRegenerate( mill ), MELT()); \
} while (0)

#define INLINE inline

INLINE void needs(? mill, Size n) {
if (vm -> myHeap -> available < n) {
freeze();
millRegenerate(mill);
melt();
}
}

Won't work.

FREEZE() is a macro, MELT is a macro, both of them use variables
available where NEEDS is called - such as, for example, `vm`.


Pass as parameters or promote to global status. Probably the latter.
"Global" with respect to the smallest unit appropriate, of course.
And `inline` wasn't routinely available when this code was written;
furthermore, failure to inline is likely to make the code run
significantly more slowly. Since this is part of the system core,
it would matter.


Sure. If inlining really won't work and profiling shows you you do need
that performance, take the macro route.

S.
Nov 15 '05 #43

P: n/a
Skarmander wrote:
Chris Dollin wrote:
Skarmander wrote:

Chris Dollin wrote:

Sensei wrote:
<snip>>I understood why he does not use a ; at the end, but why someone would
>have such a big macro... is beyond my knowledge, something like the
>xge_whatever stuff I found... :)
How big is "big"?

#define NEEDS(mill, n) \
do { \
if (vm->myHeap->available < (Size) (n)) \
(FREEZE(), millRegenerate( mill ), MELT()); \
} while (0)
#define INLINE inline

INLINE void needs(? mill, Size n) {
if (vm -> myHeap -> available < n) {
freeze();
millRegenerate(mill);
melt();
}
}

Won't work.

FREEZE() is a macro, MELT is a macro, both of them use variables
available where NEEDS is called - such as, for example, `vm`.


Pass as parameters or promote to global status. Probably the latter.
"Global" with respect to the smallest unit appropriate, of course.
And `inline` wasn't routinely available when this code was written;
furthermore, failure to inline is likely to make the code run
significantly more slowly. Since this is part of the system core,
it would matter.


Sure. If inlining really won't work and profiling shows you you do need
that performance, take the macro route.


Inlining really didn't work.

--
Chris "electric hedgehog" Dollin
Essare - to be. Essen - to be at Messe Essen for SPIEL 05.
Nov 15 '05 #44

This discussion thread is closed

Replies have been disabled for this discussion.