#if #elif etc whats wrong?

Go To Last Post
20 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

here is a simple thing I wrote, and thought it would work right away. but whatever I do, after compiling, OFFSET equals the last #elif clause, so in this case it is always OFFSET3 no matter what I define as OFFSET

where is my mistake ?

#define OFFSET3 0x50
#define OFFSET2 0x60
#define OFFSET1 0x70
#define OFFSET OFFSET1


#if(OFFSET==OFFSET1)
#define OFFSET_ADR 24

#elif (OFFSET==OFFSET2)
#define OFFSET_ADR 16

#elif (OFFSET==OFFSET3)
#define OFFSET_ADR 8
#endif

thank you

Alex

There are 10 kinds of people... those who digg binary and those who don't

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It looks fine to me.

Are you sure that you are building from this file?

As a debug method, just do

#define OFFSET3 0x50
#define OFFSET2 0x60
#define OFFSET1 0x70
#define OFFSET OFFSET1


#if(OFFSET==OFFSET1)
#define OFFSET_ADR 24
#warning OFFSET_ADR is 24
#elif (OFFSET==OFFSET2)
#define OFFSET_ADR 16
#warning OFFSET_ADR is 16
#elif (OFFSET==OFFSET3)
#define OFFSET_ADR 8
#warning OFFSET_ADR is 8
#endif

David.

p.s. Just tried it with Rowley. It works fine.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#define OFFSET3 0x50
#define OFFSET2 0x60
#define OFFSET1 0x70
#define OFFSET OFFSET1


#if(OFFSET==OFFSET1)
#define OFFSET_ADR 24

#elif (OFFSET==OFFSET2)
#define OFFSET_ADR 16

#elif (OFFSET==OFFSET3)
#define OFFSET_ADR 8
#endif

#include 

int main( void )
{
    printf( "%d\n", OFFSET_ADR );
    return 0;
}

// $ gcc macros.c && ./a.out
// 24

Looks like your conclusion is faulty, or your compiler is.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It is a rather big project... many #includes, many source files... I tryed to reproduce the structure of the problem, since there is no way I can post the whole.
I tryed your debug idea, and i get 3 times (in a row)
#warning OFFSET_ADR is 24
but when i check OFFSET_ADR it is 0x50.
I will now have to try and compile despite this problem, and load OFFSET_ADR to a real RAM var... until now I could only check the AStudio macro-select parser.

will get back with news...
Alex

There are 10 kinds of people... those who digg binary and those who don't

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

... news is here.. it appears that It compiles correct, when I run it, and load (for no reason) the OFFSET_ADR on a variable. So I must assume that the AStudio tooltip is confused .... Thank you for your time!

Alex

There are 10 kinds of people... those who digg binary and those who don't

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would not trust any Tooltip from a preprocessor conditional. The proof of the pudding is in the actual compilation.
Hence the use of #warning.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For the future add -save-temps to your compilation and then study the .i file to see the results of pre-processing.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

FWIW, I seem to recall that we have concluded in the past that the code driving tooltips, intellisense and such is distinctively separate from the compiler per se. In essence there are two sets of parsers, semantic analyzers, symbol tables etc that drive to different "aspects of the IDE experience".

At the end of the day one should trust the compiler proper. (Similar to that you should trust the code executing on a real chip rather than a simulator.)

Don't get me wrong - tooltips, intellisense, simulators and such can be a good help. But when there are strangeness's or discrepancies the tool chain proper is king.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think you're right. Realtime parsing is often done by "Clang" which is a front end for LLVM which is trying to be an alternative to GCC.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

I am also having trouble with pre-processor conditionals. This is a really strange one. I provided a code snippet below.

Before myFunc() is called,

#define FCLK_IN_USE FCLK_3M68

is valid in one of my header files.

However, upon compilation I get a warning for this module as follows:

"warning: unused variable 'temp'"

Tha above warning tells me that temp variable is declared as it should be because

FCLK_IN_USE = FCLK_3M68 is true.

However, the warning states that temp is unused which shows that

FCLK_IN_USE = FCLK_1M0 applies in the rest of the
function, which I cannot understand at all.

Please have a look at the code below and see if you can spot what the hell is wrong here.

Regards...

myFunc()
{

#if ( FCLK_IN_USE == FCLK_1M8 || FCLK_IN_USE == FCLK_8M0 || FCLK_IN_USE == FCLK_3M68 )
  unsigned int temp;
#endif

#if( FCLK_IN_USE == FCLK_1M0 )

 OCR3AH = (unsigned char)( (timer3InterruptPeriodInMs >> 8 ) & 0xFF);
 OCR3AL = (unsigned char)(timer3InterruptPeriodInMs & 0xFF);

#elif( FCLK_IN_USE == FCLK_1M8 )

 temp = ( timer3InterruptPeriodInMs << 1 );
 OCR3AH = (unsigned char)( (temp >> 8 ) & 0xFF);
 OCR3AL = (unsigned char)(temp & 0xFF);

#elif( FCLK_IN_USE == FCLK_3M68 )

 temp = ( timer3InterruptPeriodInMs << 2 );
 OCR3AH = (unsigned char)( (temp >> 8 ) & 0xFF);
 OCR3AL = (unsigned char)(temp & 0xFF);

#else

 temp = ( timer3InterruptPeriodInMs << 3 );
 OCR3AH = (unsigned char)( (temp >> 8 ) & 0xFF);
 OCR3AL = (unsigned char)(temp & 0xFF);

#endif

}// end of myFunc()
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You might want to peek at the generated code. And also exercise Cliff's tip:

Quote:

For the future add -save-temps to your compilation and then study the .i file to see the results of pre-processing.


Could it be that the optimizer saw no reason to actually use the temp variable and the warning is a byproduct?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have defined the FCLK_1M0, FCLK_1M8, FCLK_3M68 and FCLK_8M0 as enums. This is the problem. When enums are used, the #if checks have no meaning. They always return true.

This explains the warning I mentioned above. Instead of the enumerations, I #defined those values and things work as expected.

By the way, I did incorporate -save-temps as advised and that has helped a lot. I will keep that in my compiler options here on. It is extremely useful for debugging!

Regards...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

This explains the warning I mentioned above. Instead of the enumerations, I #defined those values and things work as expected.

You seriously need to understand the difference between a C compiler and a C pre-processor! The C pre-processor runs first on a .c file. The C compiler never gets to see anything involving lines starting "#" because they've all been absorbed by the pre-processor by the time the C compiler gets to see the code. Things like "enum" are in the realm of the C compiler not the pre-processor. The pre-pro is not interested in such concepts.

As Lee says, follow my advice to add -save-temps to your compilation flags and get into the habit of studying the .i files that are produced from each .c file and you will learn more about what the pre-pro does and what the C compiler gets to see.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi clawson,

Thank you for reminding me about the fundamental differences between a C compiler and a pre-processor. It has been useful.

Since the pre-processor is not interested in the enumerations, then those should not be included in any of the pre-processor directives. Otherwise, the unexpected behavior that I have observed can occur.

In the example I discussed earlier, the .i file clearly showed that the pre-processor conditionals were not working as required. What happened was the first conditional was always returning true even though it wasn't. Therefore, the C compiler gave the warning after compiling the resultant code generated after the pre-processing.

Regards...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You may be better using #ifdef/#elif defined().. tests rather than #if/#elif tests when you have mutually exclusive options like that. Then something that isn't defined will not be mistaken for 0.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks clawson. That is a good tip.

Regards...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TheCryptoman wrote:
I have defined the FCLK_1M0, FCLK_1M8, FCLK_3M68 and FCLK_8M0 as enums. This is the problem. When enums are used, the #if checks have no meaning. They always return true.

You can use normal if instead of #if with enums:

myFunc()
{
  unsigned int temp;

  if( FCLK_IN_USE == FCLK_1M0 )
  {
    OCR3AH = (unsigned char)( (timer3InterruptPeriodInMs >> 8 ) & 0xFF);
    OCR3AL = (unsigned char)(timer3InterruptPeriodInMs & 0xFF);
  }
  else if( FCLK_IN_USE == FCLK_1M8 )
  {
    temp = ( timer3InterruptPeriodInMs << 1 );
    OCR3AH = (unsigned char)( (temp >> 8 ) & 0xFF);
    OCR3AL = (unsigned char)(temp & 0xFF);
  }
  else if( FCLK_IN_USE == FCLK_3M68 )
  {
    temp = ( timer3InterruptPeriodInMs << 2 );
    OCR3AH = (unsigned char)( (temp >> 8 ) & 0xFF);
    OCR3AL = (unsigned char)(temp & 0xFF);
  }
  else
  {
    temp = ( timer3InterruptPeriodInMs << 3 );
    OCR3AH = (unsigned char)( (temp >> 8 ) & 0xFF);
    OCR3AL = (unsigned char)(temp & 0xFF);
  }
}// end of myFunc()

Compiler will optimize out the variable temp if condition are constants and the variable is not used.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi maksim,

Thank you for your suggestion. How will this method affect the program memory usage? I just don't want any excess code for part of the program that will never be used. That is why I preferred to use #if rather than if.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What he's suggesting relies on the optimiser discarding what's not needed. So as long as you don't use -O0 your study of the generated asm should confirm only the code path you require remains.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the clarification clawson. I use -O2 so this suggestion should work fine.