473,320 Members | 1,694 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,320 software developers and data experts.

Behaviour of #if

What is the correct compiler response to the code below? Mine compiles this
happily and silently (with the #if evaluating to true, naturally). An error
would be helpful.

// MONITOR_CORE.CPP
// oops, forgot to #include header that #defines
// constants REACTOR_TYPE & REACTOR_OLD_MODEL

void MonitorReactorCore()
{
#if REACTOR_TYPE == REACTOR_NEW_MODEL

// nothing to do
// monitored by hardware, with auto-shutdown

#else // REACTOR_OLD_MODEL

if(CoreOverTemperature())
ShutDownReactor();

#endif

// more monitoring code
}

David

P.S. I could not locate the answer in "The C++ Programming Language" (3rd
ed.)

Jul 19 '05 #1
18 5660
"David White" <no.email@provided> wrote in message
news:Io******************@nasal.pacific.net.au...
// constants REACTOR_TYPE & REACTOR_OLD_MODEL


REACTOR_NEW_MODEL that should be

David

Jul 19 '05 #2
On Thu, 03 Jul 2003 20:18:44 +1000, David White wrote:
What is the correct compiler response to the code below? Mine compiles this
happily and silently (with the #if evaluating to true, naturally). An error
would be helpful.

// MONITOR_CORE.CPP
// oops, forgot to #include header that #defines
// constants REACTOR_TYPE & REACTOR_OLD_MODEL

#ifndef REACTOR_TYPE
#error REACTOR_TYPE not defined
#endif
void MonitorReactorCore() [snip]
P.S. I could not locate the answer in "The C++ Programming Language" (3rd
ed.)


page 813
hth
NPV
Jul 19 '05 #3
David White wrote:
What is the correct compiler response to the code below? Mine
compiles this happily and silently (with the #if evaluating to true,
naturally). An error would be helpful. #if REACTOR_TYPE == REACTOR_NEW_MODEL


The preprocessor will convert any identifiers to 0 that remain after macro
expansion but before the expression is evaluated. So, if the names aren't
macros, you get an expression like this:

#if 0 == 0

Regards,
Paul Mensonides
Jul 19 '05 #4
"David White" <no.email@provided> wrote in message
news:Io******************@nasal.pacific.net.au...
What is the correct compiler response to the code below? Mine compiles this happily and silently (with the #if evaluating to true, naturally). An error would be helpful.

// MONITOR_CORE.CPP
// oops, forgot to #include header that #defines
// constants REACTOR_TYPE & REACTOR_OLD_MODEL

void MonitorReactorCore()
{
#if REACTOR_TYPE == REACTOR_NEW_MODEL

// nothing to do
// monitored by hardware, with auto-shutdown

#else // REACTOR_OLD_MODEL

if(CoreOverTemperature())
ShutDownReactor();

#endif

// more monitoring code
}

David

P.S. I could not locate the answer in "The C++ Programming Language" (3rd
ed.)

This illustrates yet another reason why macro programming should be kept to
a minimum. If the logic had been implemented using typed data this couldn't
have happened. For instance:

void MonitorReactorCore(reactor_enum reactor_type)
{
if (reactor_type == REACTOR_OLD_MODEL)
if (CoreOverTemperature())
ShutDownReactor();
// more monitoring code
}

If either reactor_enum or REACTOR_OLD_MODEL are not defined because of a
missing header you will get a compile time error.

And BTW, why is everybody so afraid of arguments in a function? Or return
results? Don't get me started...

--
Cycho{HHR}
http://home.rochester.rr.com/cyhome/
Jul 19 '05 #5

Paul Mensonides <le******@comcast.net> wrote in message
news:JbWMa.27617$Xm3.5727@sccrnsc02...
David White wrote:
What is the correct compiler response to the code below? Mine
compiles this happily and silently (with the #if evaluating to true,
naturally). An error would be helpful.

#if REACTOR_TYPE == REACTOR_NEW_MODEL


The preprocessor will convert any identifiers to 0 that remain after macro
expansion but before the expression is evaluated. So, if the names aren't
macros, you get an expression like this:

#if 0 == 0


Well, that's horrifying. Why 0, and not void (producing "#if == ", which
surely is an error)? It's hard to believe that anyone could argue that this
is desirable, but that's something to put in comp.std.c++.

Thanks.

David

Jul 19 '05 #6
Nils Petter Vaskinn <no@spam.for.me.invalid> wrote in message
news:pa****************************@spam.for.me.in valid...
On Thu, 03 Jul 2003 20:18:44 +1000, David White wrote:
What is the correct compiler response to the code below? Mine compiles this happily and silently (with the #if evaluating to true, naturally). An error would be helpful.

// MONITOR_CORE.CPP
// oops, forgot to #include header that #defines
// constants REACTOR_TYPE & REACTOR_OLD_MODEL


#ifndef REACTOR_TYPE
#error REACTOR_TYPE not defined
#endif


The trouble is, if I remembered to put this in every source file, I would
remember to #include the right header file, which would make the above
redundant.

Thanks.

David

Jul 19 '05 #7
David White wrote:

Paul Mensonides <le******@comcast.net> wrote in message
news:JbWMa.27617$Xm3.5727@sccrnsc02...
David White wrote:
> What is the correct compiler response to the code below? Mine
> compiles this happily and silently (with the #if evaluating to
> true, naturally). An error would be helpful.

> #if REACTOR_TYPE == REACTOR_NEW_MODEL


The preprocessor will convert any identifiers to 0 that remain after
macro
expansion but before the expression is evaluated. So, if the names
aren't macros, you get an expression like this:

#if 0 == 0


Well, that's horrifying. Why 0, and not void (producing "#if == ",
which surely is an error)?


The preprocessor doesn't know anything about types.

Jul 19 '05 #8
Rolf Magnus <ra******@t-online.de> wrote in message
news:be*************@news.t-online.com...
David White wrote:

Paul Mensonides <le******@comcast.net> wrote in message
news:JbWMa.27617$Xm3.5727@sccrnsc02...
David White wrote:
> What is the correct compiler response to the code below? Mine
> compiles this happily and silently (with the #if evaluating to
> true, naturally). An error would be helpful.

> #if REACTOR_TYPE == REACTOR_NEW_MODEL

The preprocessor will convert any identifiers to 0 that remain after
macro
expansion but before the expression is evaluated. So, if the names
aren't macros, you get an expression like this:

#if 0 == 0


Well, that's horrifying. Why 0, and not void (producing "#if == ",
which surely is an error)?


The preprocessor doesn't know anything about types.


I didn't mean 'void' in the C++ language-proper sense. I just meant nothing,
instead of assuming that an unseen symbol is an integer with value 0.

David

Jul 19 '05 #9
David White wrote:

Since I can't trust the preprocessor, I'll probably do the equivalent of
this:


You can trust the preprocessor. It will do what it's specification says
it does. If you need to determine whether a symbol has been defined use
the defined operator:

#if defined(X) && X == 0

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 19 '05 #10
David White wrote:
The preprocessor will convert any identifiers to 0 that remain after
macro expansion but before the expression is evaluated. So, if the
names aren't macros, you get an expression like this:

#if 0 == 0


Well, that's horrifying. Why 0, and not void (producing "#if == ",
which surely is an error)? It's hard to believe that anyone could
argue that this is desirable, but that's something to put in
comp.std.c++.


It is desirable for situations like "#if SYMBOL" where SYMBOL might not be
defined, e.g.

#if __cplusplus

#endif

Granted, this can be rewritten as #ifdef __cplusplus, #if defined __cplusplus,
or #if defined(__cplusplus). However, the point being that a symbol, if it has
no _other_ meaning (i.e. is not defined), is the logical equivalent of 0 in an
expression.

Regarding your "REACTOR_TYPE == REACTOR_NEW_MODEL" issue where you want it to
verify the definition for you: change the object-like macros to function-like
macros, which will yield an error like you want:

#define REACTOR_TYPE() // ...
#define REACTOR_NEW_MODEL() // ...

// ...

#if REACTOR_TYPE() == REACTOR_NEW_MODEL()

That way, if the symbols are not defined, you'll get an ill-formed expression:

#if 0() == 0()

Regards,
Paul Mensonides
Jul 19 '05 #11
Paul Mensonides wrote:
It is desirable for situations like "#if SYMBOL" where SYMBOL might
not be defined, e.g.

#if __cplusplus

#endif


Sorry, slight clarification. It is useful for situations like "#if SYMBOL"
where SYMBOL might be one of three things: zero, non-zero, or not defined.
This is less verbose then doing this:

#if defined(SYMBOL) && SYMBOL

Regards,
Paul Mensonides
Jul 19 '05 #12
Pete Becker <pe********@acm.org> wrote in message
news:3F***************@acm.org...
David White wrote:

Since I can't trust the preprocessor, I'll probably do the equivalent of
this:


You can trust the preprocessor. It will do what it's specification says
it does. If you need to determine whether a symbol has been defined use
the defined operator:

#if defined(X) && X == 0


And do what if it's not defined? It has to be one model or the other. If I
can be relied upon to check whether the symbol has been defined, then I can
be relied upon to include the header in which the symbols _are_ defined,
obviating the need to check whether they are defined. The basic problem is:
how to prevent a disaster if the programmer forgets to include the symbol
definitions (or forgets to check whether they have been defined)?

It is a little surprising that, since C++ is built upon rigorous
compile-time checking, it has a preprocessor that assumes that an undefined
symbol has a value of 0, and that this is what the programmer wants.
(Whether you like or not - and many don't - the preprocessor IS part of the
language).

David

P.S. Switching to a const enum presents its own difficulties. Where before I
had:

#if REACTOR_TYPE == REACTOR_NEW_MODEL

const int Const1 = 1;
const int Const2 = 2;

#else

const int Const1 = 3;
const int Const2 = 4;

#endif

now I have:

const int Const1 = (ReactorType == ReactorNewModel) ? 1 : 3;
const int Const2 = (ReactorType == ReactorNewModel) ? 2 : 4;

I only hope I don't have to add three more model types.

David

Jul 19 '05 #13
Paul Mensonides <le******@comcast.net> wrote in message
news:mL4Na.6248$I8.2760@rwcrnsc53...
David White wrote:
The preprocessor will convert any identifiers to 0 that remain after
macro expansion but before the expression is evaluated. So, if the
names aren't macros, you get an expression like this:

#if 0 == 0
Well, that's horrifying. Why 0, and not void (producing "#if == ",
which surely is an error)? It's hard to believe that anyone could
argue that this is desirable, but that's something to put in
comp.std.c++.


It is desirable for situations like "#if SYMBOL" where SYMBOL might not be
defined, e.g.

#if __cplusplus

#endif

Granted, this can be rewritten as #ifdef __cplusplus, #if defined

__cplusplus, or #if defined(__cplusplus). However, the point being that a symbol, if it has no _other_ meaning (i.e. is not defined), is the logical equivalent of 0 in an expression.

Regarding your "REACTOR_TYPE == REACTOR_NEW_MODEL" issue where you want it to verify the definition for you: change the object-like macros to function-like macros, which will yield an error like you want:

#define REACTOR_TYPE() // ...
#define REACTOR_NEW_MODEL() // ...

// ...

#if REACTOR_TYPE() == REACTOR_NEW_MODEL()

That way, if the symbols are not defined, you'll get an ill-formed expression:
#if 0() == 0()


Thanks. That might be the answer I'm looking for.

David

Jul 19 '05 #14
David White <no@email.provided> wrote in message
news:S0******************@nasal.pacific.net.au...
Paul Mensonides <le******@comcast.net> wrote in message
news:mL4Na.6248$I8.2760@rwcrnsc53...
#if REACTOR_TYPE() == REACTOR_NEW_MODEL()

That way, if the symbols are not defined, you'll get an ill-formed

expression:

#if 0() == 0()


Thanks. That might be the answer I'm looking for.


.... as long as no one forgets the (), I just realized. Still, it's much
better.

David

Jul 19 '05 #15
David White wrote:

It has to be one model or the other. If I
can be relied upon to check whether the symbol has been defined, then I can
be relied upon to include the header in which the symbols _are_ defined,
obviating the need to check whether they are defined. The basic problem is:
how to prevent a disaster if the programmer forgets to include the symbol
definitions (or forgets to check whether they have been defined)?
Oh, I see: you don't trust other programmers, so you want to control
what they do. Sorry, won't work. Document what your code is designed to
do and how to use it. That's where your job ends.

It is a little surprising that, since C++ is built upon rigorous
compile-time checking, it has a preprocessor that assumes that an undefined
symbol has a value of 0, and that this is what the programmer wants.


Whatever the language does, someone will want to do something
differently. Work with what's there.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 19 '05 #16
"Pete Becker" <pe********@acm.org> wrote in message
news:3F***************@acm.org...
David White wrote:

It has to be one model or the other. If I
can be relied upon to check whether the symbol has been defined, then I can be relied upon to include the header in which the symbols _are_ defined,
obviating the need to check whether they are defined. The basic problem is: how to prevent a disaster if the programmer forgets to include the symbol definitions (or forgets to check whether they have been defined)?


Oh, I see: you don't trust other programmers, so you want to control
what they do.


No, I had myself in mind actually. But now that you mention it, I don't
trust other programmers either. If programmers could be trusted, compilers
would not need error messages.

David

Jul 19 '05 #17
On Fri, 04 Jul 2003 08:49:55 +1000, David White wrote:
The trouble is, if I remembered to put this in every source file, I
would remember to #include the right header file, which would make the
above redundant.


I don't know which compiler you use but gcc-s preprosessor has an option
(-Wundef) to warn you when an undefined identifier is used (and expanded
to 0) in an #if.

Read you preprosesors documentation, maybe your has a similar option and
can provide a warning for you.

hth
NPV
Jul 19 '05 #18
"Nils Petter Vaskinn" <no@spam.for.me.invalid> wrote in message
news:pa****************************@spam.for.me.in valid...
On Fri, 04 Jul 2003 08:49:55 +1000, David White wrote:
The trouble is, if I remembered to put this in every source file, I
would remember to #include the right header file, which would make the
above redundant.


I don't know which compiler you use but gcc-s preprosessor has an option
(-Wundef) to warn you when an undefined identifier is used (and expanded
to 0) in an #if.

Read you preprosesors documentation, maybe your has a similar option and
can provide a warning for you.


Good idea. I think it should default to that, but I'll happily take it if
it's there at all.

DW

Jul 19 '05 #19

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

Similar topics

2
by: Gerhard Esterhuizen | last post by:
Hi, I am observing unexpected behaviour, in the form of a corrupted class member access, from a simple C++ program that accesses an attribute declared in a virtual base class via a chain of...
2
by: Joona I Palaste | last post by:
AFAIK the C standard divides behaviour of different things into four classes. 1) Defined behaviour. The implementation must do exactly what the standard says. 2) Implementation-defined behaviour....
25
by: Nitin Bhardwaj | last post by:
Well, i'm a relatively new into C( strictly speaking : well i'm a student and have been doing & studying C programming for the last 4 years).....and also a regular reader of "comp.lang.c" I...
12
by: RoSsIaCrIiLoIA | last post by:
On Mon, 07 Feb 2005 21:28:30 GMT, Keith Thompson <kst-u@mib.org> wrote: >"Romeo Colacitti" <wwromeo@gmail.com> writes: >> Chris Torek wrote: >>> In article <4205BD5C.6DC8@mindspring.com> >>>...
31
by: DeltaOne | last post by:
#include<stdio.h> typedef struct test{ int i; int j; }test; main(){ test var; var.i=10; var.j=20;
4
by: | last post by:
I have earlier used an HttpModule that did URL rewrites on the BeginRequest event. Now I am trying to use the same module in a different application on a new and upgraded machine (winxp sp2). ...
26
by: Frederick Gotham | last post by:
I have a general idea of the different kinds of behaviour described by the C Standard, such as: (1) Well-defined behaviour: int a = 2, b = 3; int c = a + b; (Jist: The code will work...
285
by: Sheth Raxit | last post by:
Machine 1 : bash-3.00$ uname -a SunOS <hostname5.10 Generic_118822-30 sun4u sparc SUNW,Sun-Fire-280R bash-3.00$ gcc -v Reading specs from /usr/local/lib/gcc-lib/sparc-sun-solaris2.8/2.95.3/...
12
by: Franz Hose | last post by:
the following program, when compiled with gcc and '-std=c99', gcc says test.c:6: error: jump into scope of identifier with variably modified type that is, it does not even compile. ...
173
by: Ron Ford | last post by:
I'm looking for a freeware c99 compiler for windows. I had intended to use MS's Visual C++ Express and use its C capability. In the past with my MS products, I've simply needed to make .c the...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
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...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
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...

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.