how to use logical OR operation between macro and global variable - c

input.c and output.h two files, which are in different location,data in the output.c will be printed out when macro "HEXA" is activated.
consider macro "HEXA" is disabled,and i want to print the data in output.h file when i call "active_fun" function in input.c. so i have used a global variable its value is updated when function "active_fun" called and global variable is used in .h file to print data as shown below
input.c -->
int var=0;
int active_fun (void)
{
var =1;
}
output.h --->
#ifdef HEXA|| (var ==1)
printf("var value is one");
#endif
(i have also used #ifdef HEXA || defined(var ==1) even this logic also didn't worked)
i want to print the data in .h file when macro "HEXA" is activated and by the active_fun (when macro "HEXA" is disabled).
is there any other way to print the data in .h file.

IMO you should prefer being direct and readable:
int should_print = var;
#ifdef HEXA
should_print = 1;
#endif
if (should_print)
{
printf("var value is one");
}
Alternatively:
#ifndef HEXA
#define HEXA 0
#endif
if (HEXA || var)
{
printf("var value is one");
}
Note: I've also simplified your var checks on the assumption that it will only ever be 0 or 1.

You could do something like this:
/*
* If x can be expanded then the expanded version will be stringified
* unlike regular #x
*/
#define PPSTRFY(x) #x
#define IS_MACRO_DEFINED(m) strcmp(#m, PPSTRFY(m))
/* --- */
if (IS_MACRO_DEFINED(HEXA) || var == 1)
printf("var value is one");
It only won't work if you #define HEXA HEXA but I don't see why you would want to do that. And if you're not including string.h I think replacing strcmp(#x, PPSTRFY(x)) with (#x != PPSTRFY(x)) should work the same since identical string literals should have the same address.

Related

create program modes using #if in c

I am trying to create two modes for a program using #if and #define but the second mode isn't working why is that ?
I would aslo appreciate it if you could suggest a better way to do this.
Here's my code:
#include "Types.h"
#include <stdio.h>
void main (void)
{
u32 m;
u32 flag = 1;
do
{
printf("\nWelcome\nPress 1 for Admin mode\nPress 2 for User Mode\nYour Choice:");
scanf("%d",&m);
if (m==1)
{
#define m 1
flag = 0;
}
else if (m==2)
{
#define n 2
flag = 0;
}
else
{
printf("\nInvalid number \nPlease Try again");
}
}while(flag);
//using conditional directive to run only the portion of the code for the slected mode
#if m==1
printf("Welcome to admin mode");
#elif n==2
printf("Welcome to user mode");
#endif
}
The #define and ifs are part of the preprocessor macro.
One way to think about them is to imagine the compiler going through your files and cutting and pasting in them as an early step in compilation. When you define for example PI to be 3, it will paste 3's everywhere in your code that you have written the PI. This then tells us that it won't matter which branch of m == 1 or 2 we go down when running the program - all the preprocessor editing has already been completed!
One way to get the program built in a certain mode would be to use a flag when compiling, for example -D DEBUG. Note that we cannot use this to select mode in an already compiled program.
Preprocessor Options:
-D=
Adds an implicit #define into the predefines buffer which is read before the source file is
preprocessed.
The preprocessor if #if can only interpret values which are known at proprocessing time, which is even before compile time.
It cannot read values from variables like your u32 m.
On the other hand, a preprocessor #define is also only done at preprocessing time, it will not be influenced by being within the "then" branch or the "else" branch of an if.
Doing #defines within code blocks (e.g. if branches), or even within a function, is there for not recommended.
You did not specify how your code misbehaves, but I would not be surprised, if the #if always acts admin mode. There has been a #define m 1 before in the file (no matter what path runtime execution took), so the proprocessor will take the first option.
In the C language, al the directives starting with "#" are used by the preprocessor. The preprocessor scans your file before compilation so that "variable" m is hardcoded and you can't change it in runtime (when you're running the program).
Also, the "m" variable is declared but not used.
To change the behaviour of the program on runtime, you should use a standard variable and use a switch-case to check for the variable's value and run the appropriate code.
I would also recommend using standard types defined by the language like "int" or "char" as they have better portability through the different architectures.
Your code could be like this
#include <stdio.h>
int main (void)
{
int m;
do
{
printf("\nWelcome\nPress 1 for Admin mode\nPress 2 for User Mode\nYour Choice:");
scanf("%d",&m);
if (m == 1)
{
printf("Welcome to admin mode");
return 0;
}
else if (m == 2)
{
printf("Welcome to user mode");
return 0;
}
else
{
printf("\nInvalid number \nPlease Try again");
}
}while(m != 1 || m != 2);
return 0;
}

How to separate #defined arguments in C

I'm working on an embedded project and I have all the ports and pins defined like this:
#define SENSOR_1 gpioPortA,15
Is there a way to extract just the integer without creating a new #define?
So far I used a typedef and assigned the pin value from the #define like so:
typedef struct
{
GPIO_Port_TypeDef port;
uint8_t pin;
}sensor_t;
sensor_t sensor1 = {SENSOR_1};
/* Now sensor1.pin is the pin value */
but I want to pass the pin to a switch case and I can only use constant values for that and I'd rather avoid using an if statement.
Is there a way to pass the pin to a switch case without a new #define?
Short answer is no.
You could however use sensor1.pin when needed but not in case of switch statement as switch does not support variables there. In this case use if-else statement.
Or do it like this:
#define SENSOR_1_PIN 10
#define SENSOR_1 my_port,SENSOR_1_PIN
and then in switch you use SENSOR_1_PIN in case part.
switch (condition) {
case SENSOR_1_PIN:
//Do stuff
break;
//....
}
Just to remind again as it was posted in first comment on your question. Doing that is very dangerous.
Most proper way would be to do it like this:
#define SENSOR_1_PORT GPIOB
#define SENSOR_1_PIN 15
//If structure order changes here, you may lead to wrong data interpretation
sensor_t sensor1 = {SENSOR_1_PORT, SENSOR_1_PIN};
If you are C99 compliant, you may do it even more safer like this:
//If structure order changes here, your data are still properly assigned to fields
sensor_t sensor1 = {.port = SENSOR_1_PORT, .pin = SENSOR_1_PIN};
You can define a macro to extract the value from your definition.
#define GET_SECOND(x, y) y
#define PIN_VALUE(x) GET_SECOND(x)
switch (pin) {
case PIN_VALUE(SENSOR_1):
/* ... */
break;
}
PIN_VALUE must allow SENSOR_1 to be expanded via helper macro so that the second part can be extracted.
The proper solution at this point is to re-design the definitions into something that makes more sense, or alternatively create new constants.
As a last resort, if you are stuck with these macros, you can parse them in the following way:
#include <stdio.h>
#include <stdint.h>
typedef int GPIO_Port_TypeDef; // whatever type this happens to be
typedef struct
{
GPIO_Port_TypeDef port;
uint8_t pin;
}sensor_t;
#define GET_FIELD(field,...) (sensor_t){__VA_ARGS__}.field
#define SENSOR_1 gpioPortA,15
int main (void)
{
int gpioPortA = 1;
printf("%d %d", GET_FIELD(port, SENSOR_1), GET_FIELD(pin, SENSOR_1));
}
The type-generic version would be:
#define GET_FIELD(type, field, ...) (type){__VA_ARGS__}.field
...
printf("%d %d", GET_FIELD(sensor_t, port, SENSOR_1), GET_FIELD(sensor_t, pin, SENSOR_1));
This scales variably no matter how many fields there are. This is however not recommended practice. Macros in general, and variadic macros in particular, should be avoided.
As for how to use run-time variables in case - you can't. Use an if-else if statement instead.
What about inserting a define inside a define ? Instead of directly adding 15, you could make a define holding 15 and insert it elsewhere.
E.g:
#define SENSORVAL 15
#define SENSOR_1 gpioPortA,SENSORVAL
typedef struct
{
GPIO_Port_TypeDef port;
uint8_t pin;
}sensor_t;
sensor_t sensor1 = {SENSOR_1};
/* Now sensor1.pin is the pin value */

C language, giving value to char in an if-else statement?

I am trying to use define like this
`printf ("1st Account:");
scanf("%i",&AN1);
printf ("Value of 1st Account:");
scanf("%f",&VAN1);
printf ("2nd Account:");
scanf("%i",&AN2);
printf ("Value of 2nd Account:");
scanf("%f",&VAN2);
system("pause");
system("cls");
if (AN1==101)
#define CAN1 "Cash"
else if (AN1==102)
#define CAN1 "Accounts Receivable"
else if (AN1==104)
#define CAN1 "Notes Receivable"`
and so on
Obviously, it didn't work since define is for the whole program and is not read only within the if statement.
Does anyone know how to make it work?
I need to display it later so like so
`printf ("Your 1st account name is: %s with the value of %.2f.\n",CAN1,VAN1);
printf ("Your 2nd account name is: %s with the value of %.2f.\n",CAN2,VAN2);`
Use variable instead of define:
const char *can1 ="unknown";
if (AN1==101)
can1 = "Cash";
else if (AN1==102)
can1 = "Accounts Receivable";
else if (AN1==104)
can1 = "Notes Receivable";
define is processed in compile time while your value is only known in runtime.
As you correctly observed, #define statements and preprocessor directives in general are evaluated before compile time. The preprocessor processes the file, outputs the preprocessed one, and passes it to the compiler, which eventually generates object files and/or executables.
The preprocessor has no notion of scopes, braces, grammar, or language constructs. It just parses the source file, substitutes macro occurrences, and performs other meta-stuff.
As a replacement, you can use string literals:
const char* ptr;
if (that)
ptr = "that";
else
ptr = "else";
String literals cannot go out of scope because they exist for the whole runtime of the program; they are usually stored within the very core image of the executable.
define is handled in preprocessing, at compile time. You can't conditionally define things at runtime.
You can assign constants to a pointer though:
#include <stdio.h>
int main(void)
{
char *can1;
int an1 = 0;
if (an1 == 0)
can1 = "Cash";
else if (an1 == 102)
can1 = "Accounts Receivable";
else if (an1 == 104)
can1 = "Notes Receivable";
printf("%s\n", can1);
}

Macro for run-once conditioning

I am trying to build a macro that runs a code only once.
Very useful for example if you loop a code and want something inside to happen only once. The easy to use method:
static int checksum;
for( ; ; )
{
if(checksum == 0) { checksum == 1; // ... }
}
But it is a bit wasteful and confusing. So I have this macros that use checking bits instead of checking true/false state of a variable:
#define CHECKSUM(d) static d checksum_boolean
#define CHECKSUM_IF(x) if( ~(checksum_boolean >> x) & 1) \
{ \
checksum_boolean |= 1 << x;
#define CHECKSUM_END }1
The 1 at the end is to force the user to put semi-colon at the end. In my compiler this is allowed.
The problem is figuring out how to do this without having the user to specify x (n bit to be checked).
So he can use this:
CHECKSUM(char); // 7 run-once codes can be used
for( ; ; )
{
CHECKSUM_IF
// code..
CHECKSUM_END;
}
Ideas how can I achieve this?
I guess you're saying you want the macro to somehow automatically track which bit of your bitmask contains the flag for the current test. You could do it like this:
#define CHECKSUM(d) static d checksum_boolean; \
d checksum_mask
#define CHECKSUM_START do { checksum_mask = 1; } while (0)
#define CHECKSUM_IF do { \
if (!(checksum_boolean & checksum_mask)) { \
checksum_boolean |= checksum_mask;
#define CHECKSUM_END \
} \
checksum_mask <<= 1; \
} while (0)
#define CHECKSUM_RESET(i) do { checksum_boolean &= ~((uintmax_t) 1 << (i)); } while (0)
Which you might use like this:
CHECKSUM(char); // 7 run-once codes can be used
for( ; ; )
{
CHECKSUM_START;
CHECKSUM_IF
// code..
CHECKSUM_END;
CHECKSUM_IF
// other code..
CHECKSUM_END;
}
Note, however, that that has severe limitations:
The CHECKSUM_START macro and all the corresponding CHECKSUM_IF macros must all appear in the same scope
Control must always pass through CHECKSUM_START before any of the CHECKSUM_IF blocks
Control must always reach the CHECKSUM_IF blocks in the same order. It may only skip a CHECKSUM_IF block if it also skips all subsequent ones that use the same checksum bitmask.
Those constraints arise because the preprocessor cannot count.
To put it another way, barring macro redefinitions, a macro without any arguments always expands to exactly the same text. Therefore, if you don't use a macro argument to indicate which flag bit applies in each case then that needs to be tracked at run time.

concatenate the variable using Macro

I have different Address in Macro's. Which I need to pick any of the address depends on my application. Here the Details below.
#define Location1_Subset1_Sub1 0x011F
#define Location1_Subset1_Sub2 0x0150
#define Location1_Subset1_Sub3 0x0170
#define Location1_Subset2_Sub1 0x0190
#define Location1_Subset2_Sub2 0x01AF
#define Location1_Subset2_Sub3 0x01EF
#define Location2_Subset1_Sub1 0x0211
#define Location2_Subset1_Sub2 0x0230
#define Location2_Subset1_Sub3 0x0240
#define Location2_Subset2_Sub1 0x027F
#define Location2_Subset2_Sub2 0x02A0
#define Location2_Subset2_Sub3 0x02EF
The above Macros is for Address.
if(cond)
{
var1 = 1;
if(cond)
{
var2 = 2;
}
if(cond)
{
var3 = 1;
}
}
uint32 = Read_Address = fn(var1, var2, var3);
This is an example of my application. Based on the var1, var2 and var3, macro should pick the respective address. According to example above. It should pick the Address Location1_Subset2_sub1.
I need to define one macro, which will concatenate the variable. I tried with below macro, which is not right.
#define fn(var1,var2,var3) (Location##var1_Subset##var2_sub##var3)
It is concat the string "Locationvar1_Subsetvar2_subvar3". But I want which will concate the value in var's. I Would be thankful, if some one guide me.
Macros and variables live in entirely different worlds: they cannot read the value of variables. Macros are expanded during the preprocessing stage, so your program isn't even compiled yet. They can only do purely textual manipulation of your source code.
Consider storing your constants in a static array:
static const uint32 fn[2][2][3] = {
{
{0x011F, 0x0150, 0x0170},
{0x0190, 0x01AF, 0x01EF}
},
/* ... */
};
Then you can access them directly with var1 to var3 as indices:
uint32 Read_Address = fn[var1 - 1][var2 - 1][var3 - 1];
Use this source code to concat the strings.
#define fn(var1,var2,var3) (Location##var1##_Subset##var2##_sub##var3)
But in your program, you can't do through this way.Becase Macro is processed in pre-compile time,not in running time.

Resources