To summarize,
macros:
has traditionally been a problem as ratfor has showed us, but it
isn't that big a problem any longer since the compilers has become
fairly good at reporting problems. Most of the things a macro does
can be replaced with a function or a const value, basically the one
thing that is uniq with macros is the ability to convert things to
strings. An example is
struct termiosBaud {
int const rate;
char const str[8];
speed_t const bits;
};
#define BLINE(x) { x, #x, B ## x}
const struct termiosBaud baudtab[] = {
BLINE(2400), // becomes: { 2400, "2400", B2400 },
BLINE(4800),
BLINE(9600),
};
Even tough that could be generated by some script before comilation,
I find it useful, since it both eases up on the typing and also
gives me fewer things to check out for, e.g. typos like "2409".
B2409 is easy to check for the compiler, but there is no such
thing with strings.
exceptions:
I saw in some ADA context it was inspired by the programmers
lazyness at checking return value. It seems to be a good way to
catch divide by zero, bound checking etc. longjmp is a very poor
replacement for that, but if it important enought you can always
do the checking yourself:
if (b == 0) { val = INT32_MAX; } // or whatever
else { val = a/b; }
error return:
when doing open(); there are actually multiple more or less equally
inportant codepaths from that. What to do when open succeeds, when
open couldn't find the file, when the file is there but you are not
allowed to open it, when you are interrupted by a signal etc.
Is that better handled by exceptions, I don't think so.
contracts:
(is it inspired from eiffel?) can just be done with if's checking
parameter and variable values at start or end of a function.
Could be useful to be formalized to support some tool.
embedded consequences:
in small systems, exception support is not available.
As for syntax, you just have to get used to it.
Regards,
/Karl Hammar