Reputation: 685
I have a project with a handful of files: source1.c source2.c source1.h source2.h. Now source1.c declares some variables and source1.h externs them (with a conditional build macro). source2.c would then use the extern variables by assigning a value to them.
The issue is that source1.h has something like the following:
#ifdef CUST1
extern type var_name;
#else
// Need to extern something or use a clever macro here but i dont like these below
//#define var_name int x (requires top of scope block usage)
//#define var_name // (doesnt compile)
//#define var_name -1 (simply doesnt compile)
//#define var_name 1= (This seems like it would reduce to unused 1==1; but doesnt work)
#endif
My build works for CUST1 but it will not work for CUST2 because var_name is never declared/outta scope when it is referenced in source2.c.
I dont want to use var_name for CUST2 and it is unreachable code in source2.c. Here is my question, how can i use a macro to #define var_name so that the assignment "goes away" or does nothing?
I could "#define var_name int x". This would put int x on the stack in the source2.c functions and assign the values in source2.c, but if it is ever referenced anywhere besides the top of a scope block, my old (C89?) compiler will error.
For example if source2.c ever had the following it would fail to compile:
unsigned short local_var = 0;
local_var = 1; //or someother value
var_name = local_var * 2;
I could wrap the logic in source2.c with the same #ifdef CUST1 macros but that seems not so good either.
If var_name was only being compared against it would not be so bad because i could just use #define var_name -1 or something that would fail all compares/switches. The issues is -1 = temp_var; does not compile because -1 cant be an lvalue.
Similiarly i cant "#define var_name //" because comments are removed before the marcos are replaced according to this:Can you #define a comment in C?
Is there a clever macro trick that will hide/remove this assignment, that does not put a local_var on the stack? I feel like there is something possible with a ternary but i cant think of it.
EDIT minimal example code:
source1.c
int var_name = 0;
source1.h
#ifdef CUST1
extern int var_name;
#else
// clever macro
#endif
source2.c
#include "source1.h"
int main(){
var_name = 1;
return 0;
}
Upvotes: 3
Views: 561
Reputation: 239171
If the code accessing var_name
in source2.c
is unreachable when CUST1
is not defined (as you seem to say), then you can define it like this:
#include <stdlib.h>
#define var_name (*(abort(), (type *)0))
This will work syntactically as an lvalue (or rvalue) of the correct type, but will abort the program if it's actually ever executed.
Upvotes: 1
Reputation: 67721
extern int varname;
#define varname __attribute__((unused)) int varname
int square(int num) {
varname = 1;
return num * num;
}
It will work at any optimization level except the -O0
Upvotes: 1
Reputation: 21
There is no direct way of hiding an assignment as you propose, but there are some alternatives:
You could use another macro:
#ifdef CUST1
extern type var_name;
/* Do the real assignment */
#define SET_VAR_TO(val) do{ var_name = (val); } while(0)
#else
/* Just evaluate for the side-effects */
#define SET_VAR_TO(val) do { val; } while(0)
#endif
And then inside source2.c replace all assignments to var_name
with SET_VAR_TO(value)
like:
int foo(void) {
/* Replace
var_name = bar();
* With: */
SET_VAR_TO(bar());
}
You could test if CUST1
is defined also in source2.c:
/* in source2.c */
int foo(void) {
#ifdef CUST1
var_name = bar();
#endif
}
In this case you could even wrap the assignment to a real function only defined in the source file:
/* in source2.c */
int set_var_to(type value) {
#ifdef CUST1
var_name = value;
#endif
}
int foo(void) {
/* Replace
var_name = bar();
* With: */
set_var_to(bar());
}
As you prefer to not duplicate code by wrapping each assignment inside an #ifdef CUST1 ... #endif
you could use the function or the macro. Remember that the option #1 will also expose the macro SET_VAR_TO
to any file that #include
s source1.h, not just source2.c.
Upvotes: 1