473,385 Members | 1,311 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Predefined macro namespace

I've been trying to track down explicit information about this for some time.

I know that the ANSI C standard specifies the __* and _[A-Z]* macro
namespace as reserved for the compiler implementation, and playing with
a handful of compilers I can find what those specific compilers predefine,
but is there any information out there on how that reserved namespace
should be used?

If I am writing some portable code what predefined macros should I expect
to tell me what the compiler is targetting? I've seen almost random
collections of things like __win__ __WIN32__ __WIN __DOS__ __MSDOS__ __unix
__HPIX__ _M68000_ __M68000__ _M68K_ etc.

If I write a fancy new implementation to target a Bambleweeny 57 Sub-Meson
Brain what macros should I make my compiler predefine? Should I predefine
__TEA__, __tea__ or __hottea__ for the targetted i/o system and should the
datastore be __BROWN__ or __brown__ etc????

Thanks

--
JGH - www.mdfs.net
Nov 13 '05 #1
6 2699
J.G.Harston wrote:
I've been trying to track down explicit information about this for some time.

I know that the ANSI C standard specifies the __* and _[A-Z]* macro
namespace as reserved for the compiler implementation, and playing with
a handful of compilers I can find what those specific compilers predefine,
but is there any information out there on how that reserved namespace
should be used?

If I am writing some portable code what predefined macros should I expect
to tell me what the compiler is targetting? I've seen almost random
collections of things like __win__ __WIN32__ __WIN __DOS__ __MSDOS__ __unix
__HPIX__ _M68000_ __M68000__ _M68K_ etc.
I suppose there's more than one possible meaning for "portable", but I
wouldn't consider code that relies on compiler-specific predefined
macros to be portable. "Portable", at least by my definition, means that
the code will work on any implementation, so there would be no reason to
hide parts of it using preprocessor conditionals.

If I write a fancy new implementation to target a Bambleweeny 57 Sub-Meson
Brain what macros should I make my compiler predefine? Should I predefine
__TEA__, __tea__ or __hottea__ for the targetted i/o system and should the
datastore be __BROWN__ or __brown__ etc????


There is no good, topical answer to your question. These things are
inherently implementation-defined. To the best of my knowledge, the
standard makes no recommendations or requirements aside from what you've
already mentioned.

Personally, I despise #ifdef-riddled code and avoid it at all costs. I'd
recommend using alternative source files for different targets instead.
For example, suppose I have a module called coolstuff.c. Maybe this is a
generic, purely ISO C implementation, but not very efficient. I can make
a more efficient implementation for a particular platform by using
system-specific libraries. So I might create coolstuff_sparc.c,
coolstuff_x86.c, coolstuff_mips.c, etc. Then I compile and link against
whichever is most appropriate for the platform I'm compiling for.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.

Nov 13 '05 #2
In article <QO*************@newsread1.news.pas.earthlink.net> ,
us*********************@neverbox.com says...
If I am writing some portable code what predefined macros should I expect
to tell me what the compiler is targetting? I've seen almost random
collections of things like __win__ __WIN32__ __WIN __DOS__ __MSDOS__ __unix
__HPIX__ _M68000_ __M68000__ _M68K_ etc.
I suppose there's more than one possible meaning for "portable", but I
wouldn't consider code that relies on compiler-specific predefined
macros to be portable.


How about "ported"? I.e., in order to get certain types of programs
working on more than one platform, you MUST do platform-dependant things,
then add modules to support each platform that differs from one previously
implemented. That does not mean that 99% of the source can't be
completely free of such, and the remaining 1% requires attention when
adding a new platform not previously tested. I'd suggest that the above
scenario is far better than what is commonly encountered when attempting
to move source to a new platform.
"Portable", at least by my definition, means that
the code will work on any implementation, so there would be no reason to
hide parts of it using preprocessor conditionals.
Such code is very limited by the confines of the standard C "sandbox".
Personally, I despise #ifdef-riddled code and avoid it at all costs. I'd
recommend using alternative source files for different targets instead.
For example, suppose I have a module called coolstuff.c. Maybe this is a
generic, purely ISO C implementation, but not very efficient. I can make
a more efficient implementation for a particular platform by using
system-specific libraries. So I might create coolstuff_sparc.c,
coolstuff_x86.c, coolstuff_mips.c, etc. Then I compile and link against
whichever is most appropriate for the platform I'm compiling for.


This is a great solution in cases where the implementations are
dramatically different. On some things though, the only difference
between two platforms might be the header to be included, or a three lines
of initialization code followed by the rest of it being identical. I
don't see a point in having two copies of the source file with the only
difference being trivial. That just makes maintenance a nightmare.

IOW, there is no one-size-fits-all answer and blanket statements about
the "one true way" are typically incorrect under examination.

--
Randy Howard _o
2reply remove FOOBAR \<,
______________________()/ ()______________________________________________
SCO Spam-magnet: po********@sco.com
Nov 13 '05 #3
Randy Howard wrote:
In article <QO*************@newsread1.news.pas.earthlink.net> ,
us*********************@neverbox.com says...

<snip>
"Portable", at least by my definition, means that
the code will work on any implementation, so there would be no reason to
hide parts of it using preprocessor conditionals.

Such code is very limited by the confines of the standard C "sandbox".


True. There seems to be 3 different categories of things you might want
to do in a C program: 1) Things that can be done well in straight C. 2)
Things that can be done, though somewhat poorly, in straight C. 3)
Things that simply cannot be done without extensions.

My thinking at the moment is that you could isolate those parts that
fall into categories 2 and 3, and provide implementations that work as
well as possible. For 2, this would mean that they use the
unsatisfactory but standard methods. For 3 I'm thinking that you could
abort with a diagnostic ("not implemented yet"), continue with a
diagnostic, or fail to compile, and choose which of these should occur
based on configuration option.

Personally, I despise #ifdef-riddled code and avoid it at all costs. I'd
recommend using alternative source files for different targets instead.
For example, suppose I have a module called coolstuff.c. Maybe this is a
generic, purely ISO C implementation, but not very efficient. I can make
a more efficient implementation for a particular platform by using
system-specific libraries. So I might create coolstuff_sparc.c,
coolstuff_x86.c, coolstuff_mips.c, etc. Then I compile and link against
whichever is most appropriate for the platform I'm compiling for.

This is a great solution in cases where the implementations are
dramatically different. On some things though, the only difference
between two platforms might be the header to be included, or a three lines
of initialization code followed by the rest of it being identical. I
don't see a point in having two copies of the source file with the only
difference being trivial. That just makes maintenance a nightmare.


I completely agree. That would be a disaster. Maintaining separate
nearly identical sources is a very bad idea. I'm talking somewhat
theoretically here, because I don't have much experience writing
portable code that requires a lot of non-standard extensions. I did use
a technique like this with a great deal of success a while back, while
writing networking layer that was initially intended to run on a
8051-based single-board computer, and on a PC for testing purposes (it's
much easier to test on a PC). I was surprised at how well this worked. I
didn't even bother to compile or test on the 8051 until after it was up
and running on the PC. I expected it to take up to a week to get it
running on the 8051. It took about half a day.

Even so, in hindsight I don't feel that I took exactly the right
approach. Basically I defined a set of "primitive" functions that would
have to be re-implemented for each target. These functions were very
low-level. Now I think that they were *too* low-level. Because of that,
they were quite easy to implement for a new target (because each did a
single, simple task), but they didn't really create an ideal interface.
The main system was uglier because it had to use an interface that was,
for lack of a better word, unnatural. In retrospect, I definitely should
have made the interface a higher priority.

Getting back to the main topic, your point is well taken. But even so, I
would avoid lines of code that look like this:

#if defined(__SYSTEM_A__)
DoInitStep1();
DoInitStep2();
DoInitStep3();
#elif defined(__SYSTEM_B__)
do_B_init();
#endif

/* 500 common lines follow */

Init() may be a candidate for a target-specific function, though it
would be very short in some cases, and it may not fit well in any
existing target-specific source file. Obviously creating a new source
file for every trivial thing that doesn't fit somewhere else could get
ridiculous.

Another option is to define Init conditionally:

#if defined(__SYSTEM_A__)
# define Init() do { DoInitStep1(); DoInitStep2(); \
DoInitStep3(); } while (0)
#elif defined(__SYSTEM_B__)
# define Init() do_B_init()
#endif

The advantage here is that, while it's still ugly, the ugliness is
isolated from the main part of the source, thus leaving the part that
does the real work a bit less cluttered. If Init() is going to be used
in more than one place, then this might prevent a lot of ugliness.

Finally, another alternative might be to factor out the commonality and
have some sources that are target-specific, but shared between some
similar targets.

IOW, there is no one-size-fits-all answer and blanket statements about
the "one true way" are typically incorrect under examination.


Yes, but there are more- and less-preferable methods. Personally I see
avoiding code with a lot of #ifdefs as a good goal, but, as always,
there are many things to consider and it may be that a #ifdef is the
best choice (or the least bad choice).

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.

Nov 13 '05 #4
Kevin Goodsell wrote:

I suppose there's more than one possible meaning for "portable", but I
wouldn't consider code that relies on compiler-specific predefined
macros to be portable. "Portable", at least by my definition, means that
the code will work on any implementation, so there would be no reason to
hide parts of it using preprocessor conditionals.


#include <stdio.h>
#include <limits.h>
#if INT_MAX >= 1000000
#define MILLION_FMT "d"
#else
#define MILLION_FMT "ld"
#endif

int main(void) {
printf ("For the %" MILLION_FMT "th time, Hello world!\n",
1000000);
return 0;
}

Any portability problems?

--
Er*********@sun.com
Nov 13 '05 #5
Eric Sosman wrote:
Kevin Goodsell wrote:
I suppose there's more than one possible meaning for "portable", but I
wouldn't consider code that relies on compiler-specific predefined
macros to be portable. "Portable", at least by my definition, means that
the code will work on any implementation, so there would be no reason to
hide parts of it using preprocessor conditionals.

#include <stdio.h>
#include <limits.h>
#if INT_MAX >= 1000000
#define MILLION_FMT "d"
#else
#define MILLION_FMT "ld"
#endif

int main(void) {
printf ("For the %" MILLION_FMT "th time, Hello world!\n",
1000000);
return 0;
}

Any portability problems?


Not that I can see, but it also doesn't use the type of macros I was
talking about. My last sentence above isn't as clear as it should have
been, but the first sentence mentions "compiler-specific predefined
macros", by which I meant things like __GNU_C__ and __MSVC_VER (or
however they are actually spelled).

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.

Nov 13 '05 #6
In <3F***************@sun.com> Eric Sosman <Er*********@sun.com> writes:
Kevin Goodsell wrote:

I suppose there's more than one possible meaning for "portable", but I
wouldn't consider code that relies on compiler-specific predefined
macros to be portable. "Portable", at least by my definition, means that
the code will work on any implementation, so there would be no reason to
hide parts of it using preprocessor conditionals.


#include <stdio.h>
#include <limits.h>
#if INT_MAX >= 1000000
#define MILLION_FMT "d"
#else
#define MILLION_FMT "ld"
#endif

int main(void) {
printf ("For the %" MILLION_FMT "th time, Hello world!\n",
1000000);
return 0;
}

Any portability problems?


No, but you're actually making his point. The code can be rewritten in
a much more readable fashion with no loss of portability:

#include <stdio.h>

int main(void) {
printf("For the %ldth time, Hello world!\n", 1000000L);
return 0;
}

Your example also shows that not being able to rely on a given type for
a given purpose destroys the code readability. If hardcoded long is
not an option for your example, it may be worth considering a trade
off between portability to obscure platforms and readable code:

#include <stdio.h>
#include <limits.h>
#if INT_MAX < 1000000
#error "This program requires a wider int"
#endif

int main(void) {
printf("For the %dth time, Hello world!\n", 1000000);
return 0;
}

Such a trade off was probably out of question 15 years ago, but times have
changed...

Programming is more a matter of making the right choices than of following
the "right" religion.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #7

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

Similar topics

20
by: Dead RAM | last post by:
Hey people, i'll try to keep this short ;) Here is what I want to type (or at least close too)... #define VER_BUILD 1 #define STR_VER_BUILD "VER_BUILD" But what happends is...
6
by: marco_segurini | last post by:
Hi, I like to know if this is a good way to remove 'line 18' from compilation when DBG is not defined (I dislike to wrap 'line 18' using #if/#endif pair) of if there are better ways (always...
6
by: cody | last post by:
where can i find a list of all predefined preprocessor macros in c#? i searched in the msdn but i can't find it. i now there is at lest one: DEBUG. but what else? -- cody ...
5
by: sathya_me | last post by:
friends, Please go through the following code which I have downloaded from Bob Stout (Snippets): #include <stdio.h>
0
by: Chris Ellis | last post by:
Hi, I'm trying to write a macro that will generate managed c++ wrappers of map. I want a managed iterator and a managed map. I successfully built a pair of classes (iterator and map) that work...
3
by: casul | last post by:
Hi All, I was told there were a few macro gurus on this group :) I'm trying to define a macro that will allow me to write the following code : #include MY_MACRO( NAME, SPACE )
3
by: NickP | last post by:
Hi there, I am trying to do a reflection only load of an assembly, within a new appdomain, within a macro. i.e. create new app domain instantiate class run class
2
by: utab | last post by:
Dear all, I was looking at a simple code on an exercise question. In the code, there is a conditional inclusion dependent on __GNUC__ #include <algorithm> #include <iomanip> #ifndef __GNUC__...
1
by: rk | last post by:
Is there a predefined macro set when the TR1 extensions from the "Visual C++ 2008 feature pack" are installed? Thanks rk
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 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 former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

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.