View Full Version : #define and #ifdef/endif
If I have code that says (example only) if(rc_dig_in01==1)
#define PROG1
else if(rc_dig_in02==1)
#define PROG2
#ifdef PROG1
printf("Hello, world.");
#endif
#ifdef PROG2
printf("FIRST Robotics");
#endif
Will the printf's change when i flip either of the switches? Basically, my question is if code between #ifdef/#endif is loaded onto the robot, and whether or not variables can be defined on the fly, based on switch input.
Thank you in advance,
Chris Hibner
29-04-2005, 15:20
That should not work. #define statements, #ifdef, #endif, and anything starting with the # symbol are preprocessor directives. Therefore, they are not runtime code - they just tell the compiler how to compile. They do nothing at run time.
devicenull
29-04-2005, 15:23
#ifdef PROG1
printf("Hello, world.");
#endif
#ifdef PROG2
printf("FIRST Robotics");
#endif
If we #define PROG1, then it puts the "Hello, world" printf in.
If we #define PROG2, then it puts the "FIRST Robotics" printf in.
I used these for a few sensor values that differed from our practice to competition robot.. I'll post the code we used when I get a chance.
Dave Scheck
29-04-2005, 15:27
...Chris posted while I was typing this....
Short answer is that #define and #if switches are processed before the compiler ever sees the code. Therefore you can't do what you are trying to do. You'd be better off storing the program number into a variable and deciding what to do based on that
enum
{
PROG_DO_NOTHING = 0,
PROG1,
PROG2
};
static int g_prog_num = PROG_DO_NOTHING;
....
if(rc_dig_in01==1)
{
g_prog_num = PROG1;
}
else if(rc_dig_in02==1)
{
g_prog_num = PROG2;
}
switch(g_prog_num)
{
case PROG1:
printf("Hello, world.");
break;
case PROG2:
printf("FIRST Robotics");
break;
default:
printf("DO NOTHING");
break;
}
Dave Scheck
29-04-2005, 15:30
I used these for a few sensor values that differed from our practice to competition robot.We did this as well. This is a pretty common practice.
However, the toggling of your #defines happens before you compile, not at runtime like it looks like Dan was suggesting.
...Chris posted while I was typing this....
Short answer is that #define and #if switches are processed before the compiler ever sees the code. Therefore you can't do what you are trying to do. You'd be better off storing the program number into a variable and deciding what to do based on that
enum
{
PROG_DO_NOTHING = 0,
PROG1,
PROG2
};
static int g_prog_num = PROG_DO_NOTHING;
....
if(rc_dig_in01==1)
{
g_prog_num = PROG1;
}
else if(rc_dig_in02==1)
{
g_prog_num = PROG2;
}
switch(g_prog_num)
{
case PROG1:
printf("Hello, world.");
break;
case PROG2:
printf("FIRST Robotics");
break;
default:
printf("DO NOTHING");
break;
}
Thank you very much for all the replies.
Dave, I am unfamiliar with the 'enum' command, what does it do? Assign values to the identities inside, ascending from the value assigned to the first identity?:confused:
Again, thank you very much, :D
Dave Scheck
29-04-2005, 17:27
Dave, I am unfamiliar with the 'enum' command, what does it do? Assign values to the identities inside, ascending from the value assigned to the first identity?:confused:The enum represents an "enumeration" or "enumerated list". Your interpretation is correct. It creates a list of constants to be used later in your code. The constants are numbered by adding one to the previous value. You can also change the numbering scheme whenever you want to by doing the following
//This is equivalent to
#define STEP_A 0
#define STEP_B (STEP_A + 1)
#define STEP_C 5
#define STEP_D (STEP_C+1)
enum
{
STEP_A = 0,
STEP_B,
STEP_C = 5,
STEP_D,
}One of the benefits is that you don't have to define the values for the constants as they will autoincrement. If used properly, you won't have to worry about accidentally reusing numbers. You will also be able to renumber the constants simply by rearranging them in the enum structure. Here's an example...
Say that you have 3 steps to a process defined as #defines
#define STEP_A 1
#define STEP_B 2
#define STEP_C 3You have your constants and they work just fine. During testing, you realize that you need to add STEP_D before STEP_C. You make the following change to your code
#define STEP_A 1
#define STEP_B 2
#define STEP_C 3
#define STEP_D 4While there is nothing wrong with this, your constants don't reflect the fact that STEP_D occurs before STEP_C.
If your original code was written with enumsenum
{
STEP_A = 1,
STEP_B,
STEP_C
};You could easilly add STEP_D and have the step order make senseenum
{
STEP_A = 1,
STEP_B,
STEP_D,
STEP_C
};
Unlike a #define, these constants will reside in the memory space of your program, as opposed to being substituded in pre-compilation. This may be a downside if you have limited memory or speed.
In the context that I used in my original response, #defines would have been just fine, I just chose to go with the enum because I wasn't too concerned with the values that the constants took on....I was more interested in having unique constants.
You can find some more info about enums here (http://www.phim.unibe.ch/comp_doc/c_manual/C/SYNTAX/enum.html)
Ok, now, I have another question. Can I use 'enum' in a header, and just include that header in all files that I need the constants declared in enum?
Thank you,
Dan
Dave Scheck
29-04-2005, 17:48
Yup, we do it all the time. Remember that when you do a #include that it is the same thing as copy/pasting the included file into your current file.
One thing to be careful of is that enums have scope, so you will want to be careful with the way you name your constants.
If you ran the following
enum
{
A=1,
B
};
void my_function(void)
{
enum
{
B = 4
}
printf("A: %d B: %d\n",A,B);
}
void main(void)
{
printf("A: %d B: %d\n",A,B);
my_function();
printf("A: %d B: %d\n",A,B);
}Your output would beA: 1 B: 2
A: 1 B: 4
A: 1 B: 2
When using the scripting/navigation code provided by Kevin Watson, u would call a switch statement with the following parameter: command_list[current_command].command I want to have different scripts.
int check_switch_box(void)
{
if(rc_dig_in01==1)
return command_list_1[current_command].command;
}
So theoretically, i could call switch(check_switch_box()){} instead of switch(command_list[current_command].command){}?
That should work, right? Since command_list[current_command].command really is just a value inside a struct.
If I have code that says (example only)
Will the printf's change when i flip either of the switches? Basically, my question is if code between #ifdef/#endif is loaded onto the robot, and whether or not variables can be defined on the fly, based on switch input.
Thank you in advance,
That won't work. #define is a preprocessor directive, i.e. it won't work during run-time. A better thing to do would be to just do this directly:
if(rc_dig_in01==1)
{
printf("Hello, world.\r");
}
else if (rc_dig_in02==1)
{
printf("FIRST Robotics\r");
}
Dave Scheck
29-04-2005, 19:03
So theoretically, i could call switch(check_switch_box()){} instead of switch(command_list[current_command].command){}?I think that would work as long as check_switch_box can see current_command. Depending on where it is defined you may need an extern.
It may be a little cleaner to do it in two steps
new_cmd = check_switch_box();
switch(new_cmd)That way you have a chance to sneak in and add debug for the return value of your function.
An even cleaner way to do it would be to get your program number up front and then use pass that in to your function.
//Outside of autonomous loop....
if(rc_dig_in01==1)
{
g_prog_num = 1;
}
else if(rc_dig_in02==1)
{
g_prog_num = 2;
}
...
//Inside autonomous loop....
//Assuming that the function can see current_command
new_cmd = get_auton_command(g_prog_num);
switch(new_cmd)
{
.....
}
...
// Using unsigned ints for the sake of argument
unsigned int get_auton_command(unsigned int prog_num)
{
unsigned int command = DO_NOTHING;
if(prog_num == 1)
{
command = command_list_prog1[current_command].command
}
else if(prog_num == 2)
{
command = command_list_prog2[current_command].command
}
return command;
}
I think that would work as long as check_switch_box can see current_command. Depending on where it is defined you may need an extern.
It may be a little cleaner to do it in two steps
new_cmd = check_switch_box();
switch(new_cmd)That way you have a chance to sneak in and add debug for the return value of your function.
An even cleaner way to do it would be to get your program number up front and then use pass that in to your function.
//Outside of autonomous loop....
if(rc_dig_in01==1)
{
g_prog_num = 1;
}
else if(rc_dig_in02==1)
{
g_prog_num = 2;
}
...
//Inside autonomous loop....
//Assuming that the function can see current_command
new_cmd = get_auton_command(g_prog_num);
switch(new_cmd)
{
.....
}
...
// Using unsigned ints for the sake of argument
unsigned int get_auton_command(unsigned int prog_num)
{
unsigned int command = DO_NOTHING;
if(prog_num == 1)
{
command = command_list_prog1[current_command].command
}
else if(prog_num == 2)
{
command = command_list_prog2[current_command].command
}
return command;
}
Thanks Dave. The function robot_command() is in robot.c. That is the function that is called from user_routines_fast. Due to that fact, I am putting check_switch_box() in robot.c, so since current_command is a global declared in robot.c, check_switch_box should be able to see it, correct?
Thanks again,
vBulletin® v3.6.4, Copyright ©2000-2017, Jelsoft Enterprises Ltd.