Author Topic: Good old macros and GCC  (Read 6064 times)

0 Members and 1 Guest are viewing this topic.

Offline James

  • Contributor
  • Posts: 8
  • Country: 00
Good old macros and GCC
« on: July 30, 2011, 01:13:23 pm »
I have been playing around with some macros in AVR studio and have hit a brick wall. From memory the statement
Code: [Select]
#define     YOURCONSTANT        1
assigns the value "1" to the constant "YOURCONSTANT".

How ever, is there a way to use a variable in place of the "1" and assign its value to the constant? The idea is to allow software control through a function for example
Code: [Select]
something_init(unsigned char your_constant_value)
{
    #define     YOURCONSTANT          your_constant_value
    return YOURCONSTANT;
}

Therefore if the value of your_constant_value is "hello" or "1", then the output of the function would be "hello" or "1".

So far my macro has taken the variable name as the input and therefore outputs the name of the variable not its value (e.g the output as "your_constant_value" not "hello" or "1").

It is propably just a misunderstanding of how macros work but if someone could please help that would be great.
Thanks,
James
All electronic devices work off smoke...Once the smoke is let out they no longer work!
 

Offline Hideki

  • Frequent Contributor
  • **
  • Posts: 254
  • Country: no
Re: Good old macros and GCC
« Reply #1 on: July 30, 2011, 02:13:40 pm »
Macros work by text substitution, so before the program is fed to the actual compiler, a preprocessor will replace all YOURCONSTANT with whatever text you define it to be.
So in your example, the line:

  return YOURCONSTANT;

will be changed into:

  return your_constant_value;
 

alm

  • Guest
Re: Good old macros and GCC
« Reply #2 on: July 30, 2011, 02:46:55 pm »
To add to what Hideki says, pre-processor directives like #define are, as the name suggests, interpreted by the pre-processor, which runs before the compiler. This pre-processor has no understanding of C, so putting a #define within a function doesn't make any difference. Most styles will only use #defines in header files to make them easier to find.

You appear to attempt to abuse pre-processor directives as global variables, this won't work. Any Using YOURCONSTANT outside the something_init() function will cause the compiler to complain about an undefined variable 'your_constant_value'.

Any proper C tutorial or textbook should explain how pre-processor directives work, and how they don't.
 

Offline ruku

  • Contributor
  • Posts: 25
Re: Good old macros and GCC
« Reply #3 on: July 30, 2011, 02:54:52 pm »
Wikipedia has an excellent article on how things are handled in the C preprocessor.http://en.wikipedia.org/wiki/C_macro#Macro_definition_and_expansion

To the best of my knowledge, you can't change or re-assign the value of a constant. Otherwise, it wouldn't be... ...constant! :P

I'm not quite sure what you're trying to attempt, but there are a few things you can try... One thing you can do is macro expansion.


#define MAX(a, b) ((a > b) ? a : b)


Note the parentheses around the whole expression. This keeps the expression from being affected by order of operation.

You can also define a const variable, and allow the user (or coder) to set it once, but I'm not sure if that's what you're looking for. Global variables, perhaps?
 

Offline Mechatrommer

  • Super Contributor
  • ***
  • Posts: 10317
  • Country: my
  • reassessing directives...
Re: Good old macros and GCC
« Reply #4 on: July 30, 2011, 07:40:24 pm »
there's a proper way to do it, so use it!
Code: [Select]
something_init(unsigned char your_constant_value)
{
    unsigned char *YOURCONSTANT = &your_constant_value;
    return YOURCONSTANT;
}
put your runtime value in memory, not in #DEFINE, which stored compile time value/text.
It's extremely difficult to start life.. one features of nature.. physical laws are mathematical theory of great beauty... You may wonder Why? our knowledge shows that nature is so constructed. We simply have to accept it. One could describe the situation by saying that... (Paul Dirac)
 

alm

  • Guest
Re: Good old macros and GCC
« Reply #5 on: July 30, 2011, 08:03:43 pm »
IMO it's bad style to use full caps for YOURCONSTANT, which is not a constant in this case.

Apart from style, your_constant_value is passed by value, so it's stored on the stack. What will happen to it when something_init() returns? YOURCOSTANT is just a pointer to your_constant_value, which will be pointed at unallocated memory at that point.
 

Offline James

  • Contributor
  • Posts: 8
  • Country: 00
Re: Good old macros and GCC
« Reply #6 on: July 31, 2011, 06:57:40 am »
@Mechatrommer
Tried the code but when compiling receive the error
"expected identifier or '(' before numeric constant"

I think it will just be easier to put all the defines in the header file so the values can be changed from there.
Thanks everyone for your help,
James
All electronic devices work off smoke...Once the smoke is let out they no longer work!
 

Offline Mechatrommer

  • Super Contributor
  • ***
  • Posts: 10317
  • Country: my
  • reassessing directives...
Re: Good old macros and GCC
« Reply #7 on: July 31, 2011, 09:26:10 am »
sorry i didnt bother to check my suggested code. but u'll never find a programmer that can do it in the first try, even bill gates. the word "program" will always side by side with the word "debug". so keep trying.
It's extremely difficult to start life.. one features of nature.. physical laws are mathematical theory of great beauty... You may wonder Why? our knowledge shows that nature is so constructed. We simply have to accept it. One could describe the situation by saying that... (Paul Dirac)
 

Offline ejeffrey

  • Super Contributor
  • ***
  • Posts: 2597
  • Country: us
Re: Good old macros and GCC
« Reply #8 on: August 01, 2011, 08:44:02 am »
FWIW, at least in C++ it is now 'preferred' to use const variables and inline functions instead of #define when possible, although plenty of people still do it the other way.

For instance:

Code: [Select]
#define PI 3.1415
#define AREA_OF_CIRCLE(r) (PI*r*r)

vs.

Code: [Select]
const float PI=3.1415;
inline float area_of_circle(float r) { return PI*r*r; }

In the olden days, the former way was faster, but all C++ compilers will generate equivalent code.  The advantages of the latter are that that you get better type checking, better error messages, and you can do thinks like take the address of the variable or function in cases where you need to pass pointers.  In C you may have to use the former.  The C89 standard doesn't officially include inline, and while most or all C compilers support it, their implementations may not be compatible.

The most important use of #define is actually for conditional compilation using #if.  If you have two versions of code and need to select which one is compiled on a given platform, you would use a #define variable.  Other than that, #define macros are mostly only actually necessary when you are doing something really ugly that can't be accomplished in an inline function, like trying to imitate dynamic programming constructs in C.
 

Offline Mechatrommer

  • Super Contributor
  • ***
  • Posts: 10317
  • Country: my
  • reassessing directives...
Re: Good old macros and GCC
« Reply #9 on: August 01, 2011, 09:21:51 am »
yes but inline cannot do...
Code: [Select]
#define MYLOOP1 for (i=0;i<10;i++) { \
do some routine at beginning of loop if necessary; \

#define MYLOOP2 do some routine at the end of loop; \
}; // end of loop bracket

main() {
    MYLOOP1;
    // do something
    MYLOOP2;
};
i used this technique once, to make shortcut of alot of repeating same loop routine at the beginning of the loop throughout my code.
It's extremely difficult to start life.. one features of nature.. physical laws are mathematical theory of great beauty... You may wonder Why? our knowledge shows that nature is so constructed. We simply have to accept it. One could describe the situation by saying that... (Paul Dirac)
 

Offline ejeffrey

  • Super Contributor
  • ***
  • Posts: 2597
  • Country: us
Re: Good old macros and GCC
« Reply #10 on: August 01, 2011, 09:52:06 am »
That is what I would call a bad use of #define  :P.  Actually it is 'something really ugly that can't be accomplished in an inline function, like trying to imitate dynamic programming constructs in C.'  Dynamic languages that support lambdas can do this kind of thing properly.  C programmers are forced to make do with less powerful constructs or to abuse the preprocessor.

In C, I would try to avoid this whenever possible.  For the bare loop, it only saves a few keystrokes and significantly obfuscates the code.  If you need the extra code at the beginning and end of a loop, you can either make those functions, or make the whole loop a function that takes a callback.

Code: [Select]
const int LOOP_MAX 10;
for (i=0; i<LOOP_MAX; i++) {
   loop_enter(i);
   // CODE GOES HERE.
   loop_exit(i);
}

or:

Code: [Select]
int do_loop(int (*loop_callback)(int, float))
{
    int i;
    float f=0;

    for (i=0; i<10; i++) {
        start_iteration();
        f=loop_calback(i,f);
        end_iteration();
    }
}

Function calls can't directly modify their calling environment or declare variables, so that is somewhat limiting compared to your example.  Really, that is the whole idea: using inline functions where possible makes the code clearer and easier to debug because unwanted side-effects aren't hidden behind the macro.  Sometimes you have no choice, but it is always worth thinking about whether you can achieve your goal without ugly preprocessor hacks. 
 

Offline Mechatrommer

  • Super Contributor
  • ***
  • Posts: 10317
  • Country: my
  • reassessing directives...
Re: Good old macros and GCC
« Reply #11 on: August 01, 2011, 03:47:31 pm »
there's performance penalty calling functions within a loop, esp that performs many thousands or millions of iterations. yes its ugly, but the only method i know for the construct hack if performance is important.
« Last Edit: August 01, 2011, 03:50:05 pm by Mechatrommer »
It's extremely difficult to start life.. one features of nature.. physical laws are mathematical theory of great beauty... You may wonder Why? our knowledge shows that nature is so constructed. We simply have to accept it. One could describe the situation by saying that... (Paul Dirac)
 

Offline Bored@Work

  • Super Contributor
  • ***
  • Posts: 3933
  • Country: 00
Re: Good old macros and GCC
« Reply #12 on: August 01, 2011, 04:05:09 pm »
there's performance penalty calling functions within a loop

Use inline functions.
I delete PMs unread. If you have something to say, say it in public.
For all else: Profile->[Modify Profile]Buddies/Ignore List->Edit Ignore List
 

Offline Semantics

  • Contributor
  • Posts: 48
  • Country: us
Re: Good old macros and GCC
« Reply #13 on: August 01, 2011, 04:17:06 pm »
there's performance penalty calling functions within a loop

Use inline functions.

This. Macros are evil. Well, not too evil but parameter expanded macros make it way too easy to add subtle bugs... see examples in the link.
 

Offline Mechatrommer

  • Super Contributor
  • ***
  • Posts: 10317
  • Country: my
  • reassessing directives...
Re: Good old macros and GCC
« Reply #14 on: August 01, 2011, 04:32:17 pm »
This. Macros are evil. Well, not too evil but parameter expanded macros make it way too easy to add subtle bugs... see examples in the link.
maybe i'm the last breed (#define devil) who know exactly what that means.
It's extremely difficult to start life.. one features of nature.. physical laws are mathematical theory of great beauty... You may wonder Why? our knowledge shows that nature is so constructed. We simply have to accept it. One could describe the situation by saying that... (Paul Dirac)
 

Offline ejeffrey

  • Super Contributor
  • ***
  • Posts: 2597
  • Country: us
Re: Good old macros and GCC
« Reply #15 on: August 01, 2011, 06:55:44 pm »
Thats what they all say.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf