GIDForums  

Go Back   GIDForums > Computer Programming Forums > CPP / C++ Forum
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 03-Dec-2005, 05:01
cable_guy_67's Avatar
cable_guy_67 cable_guy_67 is offline
Senior Member
 
Join Date: Oct 2004
Location: Nescopeck, PA
Posts: 1,108
cable_guy_67 is a jewel in the roughcable_guy_67 is a jewel in the roughcable_guy_67 is a jewel in the roughcable_guy_67 is a jewel in the rough

conditional compile logic


Hello all. Could someone clarify this for me? I am a bit confused on the logic behind condidtional compile statements.

Code:
#if defined(WIN32) || defined(__EMX__) && !defined(__CYGWIN__) #if (defined(WIN32) && ! defined(__CYGWIN__))|| defined(__EMX__)

Hmm, now that I post this I think I got it.

Well, let me just talk it though anyhow, to make sure.

First Example
Either WIN32 or __EMX__ must be defined to continue. If that is true __CYGWIN__ must not be defined to compile that block. It would evaluate the same if the WIN32 and __EMX__ were wrapped in parentheses.

WIN32 defined CYGWIN not defined == COMPILE
EMX defined CYGWIN not define == COMPLE

Second Example
WIN32 is defined and __CYGWIN__ is not defined or __EMX__ is defined the block will compile.

WIN32 defined CYGWIN not defined == COMPILE
EMX defined == COMPILE


Hmmm, this seems a bit odd to me. I thought they would evaluate to the same thing. Perhaps, since EMX is an OS2 port of gcc EMX would never be defined when CYGWIN was.

Oh well, the basics of my question seem to have been answered by the OP. Maybe someone else will find this helpful.

Mark
__________________
"Opportunity is missed by most people because it comes dressed in overalls and looks like work."
--Thomas Alva Edison
"Those who would give up essential liberty to purchase a little temporary safety, deserve neither liberty nor safety."
--Benjamin Franklin
"A happy person is not a person in a certain set of circumstances, but rather a person with a certain set of attitudes."
--Hugh Downs
  #2  
Old 03-Dec-2005, 06:35
Paramesh's Avatar
Paramesh Paramesh is offline
Regular Member
 
Join Date: Sep 2005
Location: The Milky Way
Posts: 922
Paramesh is a jewel in the roughParamesh is a jewel in the roughParamesh is a jewel in the rough

Re: conditional compile logic


I'll correct that a little bit.

This:
CPP / C++ / C Code:
#if defined(WIN32) || defined(__EMX__) && !defined(__CYGWIN__)
can be expanded like this:
CPP / C++ / C Code:
#if defined(WIN32) || (defined(__EMX__) && !defined(__CYGWIN__))
defined(WIN32) is a separate entity.
defined(__EMX__) && !defined(__CYGWIN__) is a separate entity.

So, If defined(WIN32) is true, irrespective of the other things, it will compile.
And if defined(WIN32) is false, it will compile only if:
defined(__EMX__) is true, and defined(__CYGWIN__) must be false.

So:
Quote:
WIN32 defined == Compile
EMX defined CYGWIN not defined == Compile

The second one:
CPP / C++ / C Code:
#if (defined(WIN32) && ! defined(__CYGWIN__))|| defined(__EMX__)
It can be expanded as:
CPP / C++ / C Code:
#if (defined(WIN32) && ( !defined(__CYGWIN__))|| defined(__EMX__) )
defined(WIN32) is a separate entity.
!defined(__CYGWIN__))|| defined(__EMX__) is a separate entity.

So,
Quote:
WIN32 Defined, CYGWIN not defined == compile
WIN32 defined, EMX defined == compile

Regards,
Paramesh.
__________________

Don't walk in front of me, I may not follow.
Don't walk behind me, I may not lead.
Just walk beside me and be my friend.
Last edited by Paramesh : 03-Dec-2005 at 06:49. Reason: Comment edited
  #3  
Old 03-Dec-2005, 06:50
cable_guy_67's Avatar
cable_guy_67 cable_guy_67 is offline
Senior Member
 
Join Date: Oct 2004
Location: Nescopeck, PA
Posts: 1,108
cable_guy_67 is a jewel in the roughcable_guy_67 is a jewel in the roughcable_guy_67 is a jewel in the roughcable_guy_67 is a jewel in the rough

Re: conditional compile logic


Quote:
Originally Posted by Paramesh
I think that is wrong.

Wouldn't be the first time, won't be the last.

Your explanation is making my head hurt. This is what I get from it...

The || and && are evaluated by order of precedence. In your explanation, && is higher.

Something seems odd to me. Based on where I pulled this from (FLTK sources) that should not be true. I guess it's time for some additional testing...

Thanks Paramesh, I appreciate the response.

Mark
__________________
"Opportunity is missed by most people because it comes dressed in overalls and looks like work."
--Thomas Alva Edison
"Those who would give up essential liberty to purchase a little temporary safety, deserve neither liberty nor safety."
--Benjamin Franklin
"A happy person is not a person in a certain set of circumstances, but rather a person with a certain set of attitudes."
--Hugh Downs
  #4  
Old 03-Dec-2005, 07:32
Paramesh's Avatar
Paramesh Paramesh is offline
Regular Member
 
Join Date: Sep 2005
Location: The Milky Way
Posts: 922
Paramesh is a jewel in the roughParamesh is a jewel in the roughParamesh is a jewel in the rough
Arrow

Re: conditional compile logic


I tested this on Visual C++, and MingW. I dont know why this differs from FLTK sources. But Yes. I think Different compilers have different implementations.

For those who want to know how to test this:
Use 1 and 0!!!!
Like these:

FIRST:
CPP / C++ / C Code:
    if( 1 || 0 && !0 )
        printf("YES");
It will print YES. (The answer what i got is written here)
CPP / C++ / C Code:
    if( 0 || 1 && !0 )
        printf("YES");
It will print YES,
CPP / C++ / C Code:
    if( 0 || 0 && !0 )
        printf("YES");
It wont print.

SECOND:
CPP / C++ / C Code:
    if( 1 && !0 || 0 )
        printf("YES");
It will print YES.
CPP / C++ / C Code:
    if( 1 && !1 || 1 )
         printf("YES");
It will print YES.
CPP / C++ / C Code:
    if( 0 && !0 || 0 )
         printf("YES");
It wont print.

So, go on and test with whatever options you have!!!

Regards,
Paramesh.
__________________

Don't walk in front of me, I may not follow.
Don't walk behind me, I may not lead.
Just walk beside me and be my friend.
  #5  
Old 03-Dec-2005, 07:52
LuciWiz's Avatar
LuciWiz LuciWiz is offline
Moderator
 
Join Date: Jul 2004
Location: Cluj-Napoca (Romania)
Posts: 889
LuciWiz is a jewel in the roughLuciWiz is a jewel in the roughLuciWiz is a jewel in the roughLuciWiz is a jewel in the rough

Re: conditional compile logic


Quote:
Originally Posted by cable_guy_67
In your explanation, && is higher.

According to the Holly Standard, that is true. Of course, I never understood why anyone would use this obfuscated coding style; always use parenthesis, I say (and every Lisp geek is cheering ).

Best regards,
Lucian
__________________
Please read these Guidelines before posting on the forum

"A person who never made a mistake never tried anything new."
Einstein
  #6  
Old 03-Dec-2005, 07:56
cable_guy_67's Avatar
cable_guy_67 cable_guy_67 is offline
Senior Member
 
Join Date: Oct 2004
Location: Nescopeck, PA
Posts: 1,108
cable_guy_67 is a jewel in the roughcable_guy_67 is a jewel in the roughcable_guy_67 is a jewel in the roughcable_guy_67 is a jewel in the rough

Re: conditional compile logic


The only reason they do it is so common sources can be used to compile the FLTK library for any of the supported platforms. I first assumed that they would be evaluated from left to right or based on the parentheses. I'm trying some tests now.
__________________
"Opportunity is missed by most people because it comes dressed in overalls and looks like work."
--Thomas Alva Edison
"Those who would give up essential liberty to purchase a little temporary safety, deserve neither liberty nor safety."
--Benjamin Franklin
"A happy person is not a person in a certain set of circumstances, but rather a person with a certain set of attitudes."
--Hugh Downs
  #7  
Old 03-Dec-2005, 08:34
cable_guy_67's Avatar
cable_guy_67 cable_guy_67 is offline
Senior Member
 
Join Date: Oct 2004
Location: Nescopeck, PA
Posts: 1,108
cable_guy_67 is a jewel in the roughcable_guy_67 is a jewel in the roughcable_guy_67 is a jewel in the roughcable_guy_67 is a jewel in the rough

Re: conditional compile logic


Quote:
Originally Posted by Paramesh
I tested this on Visual C++, and MingW. I dont know why this differs from FLTK sources. But Yes. I think Different compilers have different implementations.

For those who want to know how to test this:
Use 1 and 0!!!!
Like these:

FIRST:
CPP / C++ / C Code:
    if( 1 || 0 && !0 )
        printf("YES");
It will print YES. (The answer what i got is written here)

<snip>


Actually, I am not concerned with regular if/etc logic, it is the conditional compile if/endif stuff. So it would make more sense to test with...

CPP / C++ / C Code:
// test 1  WIN32 defined EMX !defined  CYGWIN !defined
#include <iostream>
using std::cout;
using std::endl;

// for ease, WIN32 is DEF1, EMX is DEF2 and CYGWIN is DEF3

#define DEF1 1
//#define DEF2 1
//#define DEF3 1

int main()
{

  #if defined(DEF1) || defined(DEF2) && !defined(DEF3)
    cout << "test 1 : this will compile" << endl;
  #endif

  #if (defined(DEF1) && ! defined(DEF3))|| defined(DEF2)
    cout << "test 2 : this will compile" << endl;
  #endif

  cout << "tests complete" << endl;
  return 0;
}

Output:
Code:
$ Test1 test 1 : this will compile test 2 : this will compile tests complete

CPP / C++ / C Code:
// test 2  WIN32 defined  EMX !defined  CYGWIN defined
#include <iostream>
using std::cout;
using std::endl;

// for ease, WIN32 is DEF1, EMX is DEF2 and CYGWIN is DEF3

#define DEF1 1
//#define DEF2 1
#define DEF3 1

int main()
{

  #if defined(DEF1) || defined(DEF2) && !defined(DEF3)
    cout << "test 1 : this will compile" << endl;
  #endif

  #if (defined(DEF1) && ! defined(DEF3))|| defined(DEF2)
    cout << "test 2 : this will compile" << endl;
  #endif

  cout << "tests complete" << endl;
  return 0;
}


Output:
Code:
$ Test2 test 1 : this will compile tests complete


CPP / C++ / C Code:
// test 3 WIN32 !defined EMX defined  CYGWIN defined
#include <iostream>
using std::cout;
using std::endl;

// for ease, WIN32 is DEF1, EMX is DEF2 and CYGWIN is DEF3

// #define DEF1 1
#define DEF2 1
#define DEF3 1

int main()
{

  #if defined(DEF1) || defined(DEF2) && !defined(DEF3)
    cout << "test 1 : this will compile" << endl;
  #endif

  #if (defined(DEF1) && ! defined(DEF3))|| defined(DEF2)
    cout << "test 2 : this will compile" << endl;
  #endif

  cout << "tests complete" << endl;
  return 0;
}


Output:
Code:
$ Test3 test 2 : this will compile tests complete

CPP / C++ / C Code:
// test 4 WIN32 !defined EMX defined CYGWIN !defined
#include <iostream>
using std::cout;
using std::endl;

// for ease, WIN32 is DEF1, EMX is DEF2 and CYGWIN is DEF3

// #define DEF1 1
#define DEF2 1
// #define DEF3 1

int main()
{

  #if defined(DEF1) || defined(DEF2) && !defined(DEF3)
    cout << "test 1 : this will compile" << endl;
  #endif

  #if (defined(DEF1) && ! defined(DEF3))|| defined(DEF2)
    cout << "test 2 : this will compile" << endl;
  #endif

  cout << "tests complete" << endl;
  return 0;
}


Output:
Code:
$ Test4 test 1 : this will compile test 2 : this will compile tests complete

To really beat the dead horse...
CPP / C++ / C Code:
// test 5 WIN32 !defined EMX !defined CYGWIN !defined
#include <iostream>
using std::cout;
using std::endl;

// for ease, WIN32 is DEF1, EMX is DEF2 and CYGWIN is DEF3

// #define DEF1 1
// #define DEF2 1
// #define DEF3 1

int main()
{

  #if defined(DEF1) || defined(DEF2) && !defined(DEF3)
    cout << "test 1 : this will compile" << endl;
  #endif

  #if (defined(DEF1) && ! defined(DEF3))|| defined(DEF2)
    cout << "test 2 : this will compile" << endl;
  #endif

  cout << "tests complete" << endl;
  return 0;
}

Output:
Code:
$ Test5 tests complete

Actally the only other test would be to only define CYGWIN but since it runs under windows that would just be crazy. I can tell you the output would be...
Code:
$ Test6 tests complete


Anyhow, thanks to all for the input, I do believe I have got it.

Mark
__________________
"Opportunity is missed by most people because it comes dressed in overalls and looks like work."
--Thomas Alva Edison
"Those who would give up essential liberty to purchase a little temporary safety, deserve neither liberty nor safety."
--Benjamin Franklin
"A happy person is not a person in a certain set of circumstances, but rather a person with a certain set of attitudes."
--Hugh Downs
  #8  
Old 03-Dec-2005, 08:34
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,623
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: conditional compile logic


Quote:
Originally Posted by Paramesh
I think Different compilers have different implementations.

No way!!!

First of all: it is true that precedence rules for preprocessor expressions are the same as for C: && has higher precedence that ||.

Secondly: The precedence rules are required by the C and C++ standards.

Thirdly: The two expressions in the original post are not equal:

Lets use a, b, and c for the WIN32, __EMX__, __CYGWIN__ terms, and consider the following expressions:

Code:
First expression a || b && !c Second expression a && !c || b

With parentheses that emphasize the precedence (but don't change the precedence or the results):

Code:
First expression a || (b && !c) Second expression (a && !c) || b

In Boolean: The first expression is "a or b and c-bar", and the second is "a and c-bar or b".
(Where in boolean algebra "and" has higher precedence than "or".)

Now, by Boolean algebra identities (possibly aided by Quine-McKlusky or by Karnaugh maps), or by simply comparing truth tables, we can determine that the two expressions are not equal.

There are two cases where they differ:
Code:
a = false, b = true, c = true First expression == false Second expression == true a = true, b = false, c = true First expression == true Second expression == false

Want to try for yourself?

CPP / C++ / C Code:
#include <stdio.h>

int main()
{

  int a, b, c;
  int f1(int, int, int);
  int f2(int, int, int);
  int f3(int, int, int);
  int f4(int, int, int);


  printf(" a b c   1  2  3  4\n");
  printf("--------------------\n");
  for (a = 0; a < 2; a++) {
    for (b = 0; b < 2; b++) {
      for (c = 0; c < 2; c++) {
        printf(" %d %d %d : %d  %d  %d  %d\n", 
                a, b, c, f1(a, b, c), f2(a, b, c), f3(a, b, c), f4(a, b, c));
      }
    }
  }

  printf("\n");
  return 0;
}

int f1(int a, int b, int c)
{
  return (a || b && !c);
}

int f2(int a, int b, int c)
{
  return (a || (b && !c));
}

int f3(int a, int b, int c)
{
  return (a && !b || c);
}
int f4(int a, int b, int c)
{
  return ((a && !b) || c);
}


Output:


Code:
a b c 1 2 3 4 -------------------- 0 0 0 : 0 0 0 0 0 0 1 : 0 0 0 0 0 1 0 : 1 1 1 1 0 1 1 : 0 0 1 1 1 0 0 : 1 1 1 1 1 0 1 : 1 1 0 0 1 1 0 : 1 1 1 1 1 1 1 : 1 1 1 1

Output columns "1" and "2" are for the un-parenthesized and parenthesized versions of the first expression. Output columns are for the un-parenthesized and parenthesized version of hte second expression.

If your compiler gives different results, ask for your money back.

Now, if you go back and look at the probable intended results of the two expressions, you may (or may not) see whether they will always do the right thing for the cases of interest, and whether it makes sense to define things like this.

Regards,

Dave
  #9  
Old 03-Dec-2005, 09:07
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,623
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: conditional compile logic


Quote:
Originally Posted by LuciWiz
Of course, I never understood why anyone would use this obfuscated coding style; always use parenthesis, I say

Best regards,
Lucian

I couldn't have said it better! Why would you not use parentheses?

Well, I know that was supposed to be a rhetorical question, but I actually have an answer, based on observations of lots and lots (and lots) of C code over the years.

The C language is actually rather simple and elegant. One confusion factor is pointers, as every new C programmer knows (as well as some not-so-new ones).

The other one is the rather bewildering collection of operators on the built-in data types.

Now, to make himself/herself look more important and knowledgable than he/she really is, the C programmer typically shows how far above the common masses he/she is by making notation as obfuscatory as possible.

Pointers don't need any additional obfuscation; for most of us they are already black magic (try a 3-D array of pointers to functions that return pointers to functions whose arguments are arrays of structs.)

Now there are only two basic built-in data types in C: integer data types and floating point data types. It's pretty hard to make this look hard (although we can create composites of these that are mind-bending), but we can at least confuse the beginner by using an absolute minimum number of keystrokes for each expression. That is, leave off unnecessary parentheses. After all, a real C programmer has the precedence table on page 53 of K&R2 forever entwined with his/her soul, and to use unneccessary parentheses would surely be a sign of weakness. (Sometimes beginners have table 2-1 tattooed on their arms, but then they have to wear long-sleeved shirts for the rest of their lives.)

The occasional bug where even experienced programmers carelessly writes a+b<<c, thinking it means a+(b<<c) when actually it means (a+b)<<c is a small price to pay for having established dominion over the great unwashed masses of people-who-wish-they-were-C-programmers-but-are-confused-by-the-examples-they-see.

Regards,

Dave

P.S. Your reference to LISP (Lots of Insipid, Stupid Parentheses or was it Lots of Irritating, Spurious Parentheses?) took me back a few years. Is LISP still the darling of the non-numeric applications gurus (AI and others)? I haven't kept up with the literature lately.
  #10  
Old 03-Dec-2005, 09:16
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,623
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: conditional compile logic


Quote:
Originally Posted by cable_guy_67
Actually, I am not concerned with regular if/etc logic, it is the conditional compile if/endif stuff.

Actually the concern is whether boolean expressions in preprocessor directives obey the same precedence rules as C language expressions.

The answer is yes.

Writing a program that shows it with preprocessor directives is more tedious, but you can verify it. (It's more tedious, since preprocessor directives are fixed at compile time. You can #define and #undef identifiers anywhere in your source code, but you can't have a program loop for which an identifier is defined in one pass and undefined in another.)

For example here's a program for the first expression of your original post:

CPP / C++ / C Code:
#include <stdio.h>


/* #define a2 */
/* #define a1 */
/* #define a0 */
#if defined(a2) || defined(a1) && !defined(a0)
#define resulta 1
#else
#define resulta 0
#endif

/* #define b2 */
/* #define b1 */
#define b0
#if defined(b2) || defined(b1) && !defined(b0)
#define resultb 1
#else
#define resultb 0
#endif

/* #define c2 */
#define c1
/* #define c0 */
#if defined(c2) || defined(c1) && !defined(c0)
#define resultc 1
#else
#define resultc 0
#endif

/* #define d2 */
#define d1
#define d0
#if defined(d2) || defined(d1) && !defined(d0)
#define resultd 1
#else
#define resultd 0
#endif


#define e2
/* #define e1 */
/* #define e0 */
#if defined(e2) || defined(e1) && !defined(e0)
#define resulte 1
#else
#define resulte 0
#endif

#define f2
/* #define f1 */
#define f0
#if defined(f2) || defined(f1) && !defined(f0)
#define resultf 1
#else
#define resultf 0
#endif

#define g2
#define g1
/* define g0 */
#if defined(g2) || defined(g1) && !defined(g0)
#define resultg 1
#else
#define resultg 0
#endif

#define h2
#define h1
#define h0
#if defined(h2) || defined(h1) && !defined(h0)
#define resulth 1
#else
#define resulth 0
#endif


int main()
{
  int i;
  
  i = resulta;

  if (i) {
    printf("resulta is true\n");
  }
  else {
    printf("resulta is false\n");
  }

  i = resultb;
  if (i) {
    printf("resultb is true\n");
  }
  else {
    printf("resultb is false\n");
  }

  i = resultc;
  if (i) {
    printf("resultc is true\n");
  }
  else {
    printf("resultc is false\n");
  }

  i = resultd;
  if (i) {
    printf("resultd is true\n");
  }
  else {
    printf("resultd is false\n");
  }

  i = resulte;
  if (i) {
    printf("resulte is true\n");
  }
  else {
    printf("resulte is false\n");
  }

  i = resultf;
  if (i) {
    printf("resultf is true\n");
  }
  else {
    printf("resultf is false\n");
  }

  i = resultg;
  if (i) {
    printf("resultg is true\n");
  }
  else {
    printf("resultg is false\n");
  }

  i = resulth;
  if (i) {
    printf("resulth is true\n");
  }
  else {
    printf("resulth is false\n");
  }



  return 0;
}

Results:

Code:
resulta is false resultb is false resultc is true resultd is false resulte is true resultf is true resultg is true resulth is true

This shows the same results as output column 1 of my previous post. I leave expression number 2 as an exercise for the student (as well as the parenthesized versions of both).

Regards,

Dave
 
 

Recent GIDBlogToyota - 2008 July Promotion by Nihal

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Steps to create and compile c program in SUSE batrsau Computer Software Forum - Linux 7 03-Jun-2007 19:49
FLTK compile help machinated FLTK Forum 8 05-Mar-2005 14:52
Can't run any programs I compile, please help NotReallyHere CPP / C++ Forum 2 29-Dec-2004 15:57
logic problem? ozzytx CPP / C++ Forum 3 09-Jul-2004 02:23
Can't find logic error crystalattice CPP / C++ Forum 2 24-May-2004 19:31

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 18:10.


vBulletin, Copyright © 2000 - 2008, Jelsoft Enterprises Ltd.