C preprocessing multi pass - c

I'm a littlebit confused about the behaviour of preprocessing in c.
#include <stdio.h>
#define myMacro anotherMacro
#define anotherMacro 6
int main()
{
int dummy = myMacro;
printf("dummy = %d", dummy);
return 0;
}
in the above code snippet, the result will 6. however the the macro expansion in the initial pass will replace "myMacro" by "anotherMacro".
this is means that preprocessor will make a second pass to resolve "anotherMacro" to value 6.

The preprocessor will make a second pass. He works through the source file line per line.
So if he reaches the first define
#define myMacro anotherMacro
he will replace all occurrences of myMacro with the string anotherMacro.
The file will look like this after the line is handled:
#include <stdio.h>
#define anotherMacro 6
int main()
{
int dummy = anotherMacro;
printf("dummy = %d", dummy);
return 0;
}
Now the preprocessor could continue with the next #define
and replace every anotherMacro with the text 6

Related

Can I use "(" in preprocessor concatenation in C?

The following gives this error in GCC: pasting "func_x" and "(" does not give a valid preprocessing token
#include <stdio.h>
#define LOG_FUNC(fname) printf( #fname " %d\n", fname ## ())
int func_x(){
return 0;
}
int main(){
LOG_FUNC(func_x);
return 0;
}
However, when I hover the mouse on top of the function, it shows that the macro expands to following expression that works without a problem
printf("func_x" " %d\n", func_x())
Is it because the parenthesis is not allowed in pre processor string concatenation?
If you want to get your code to compile, change LOG_FUNC to:
#define LOG_FUNC(fname) printf( #fname " %d\n", fname())
If you want to concatenate two strings together, just write them next to each other, separated by whitespace. It is OK if they contain parens. You don't have to use the preprocessor for this, but you can:
#include <stdio.h>
#define MY_STR(f) f "(\n"
int main() {
puts(MY_STR("hi")); // outputs "hi("
return 0;
}

How can I use variable width specifiers defined by a macro in sscanf()

I am trying to specify the width of variables in a sscanf() call based on a #define that calculates its values based on another #define.
It works when the TEST define is just a single number, but when it becomes a calculation, the code fails. Have TEST call another function that contains the calculation does not work either.
The code I am working with:
#include <stdio.h>
#define A 3
#define TEST FUN()
#define FUN() (A + 2)
#define STR(X) _STR(X)
#define _STR(x) #x
int main()
{
char input[] = "Test123";
char output[10];
sscanf(input, "%" STR(TEST) "s\n", output);
printf("%s\n", output);
return 0;
}
What am I missing here?
You cannot realize an arithmetic operation as happened in your question. So, it is evaluated as (3 + 2) in string form while compiling.
My two cents reminiscent of the post,
#define STRING_LENGTH 20
#define STR(x) _STR(x)
#define _STR(x) #x
{
...
fscanf(input, "%" STR(STRING_LENGTH) "s", output);
...
}
Two macros are required because if you tried to use something like _STR directly you would just get the string "STRING_LENGTH" instead of its value.
For more click here and an example.
Just build the scanf format string during execution. For example:
const int width_modifier = FUN();
char fmt[100] = {0};
snprintf(fmt, sizeof(fmt), "%%%ds\n", width_modifier);
sscanf(input, fmt, output);
What am I missing here?
Preprocessor does text replacement, it doesn't calculate things. So "%" STR(TEST) "s\n" expands to a string containing "%" "3 + 2" "s\n", which after concatenation is "%3 + 2s", which is an invalid scanf format string.
Alternatively you can use other program to prepare the source file for compilation. A popular use is a preprocessor that preprocesses the file before compilation and that is able to calculate arithmetic. A popular choice is m4:
m4_define(`A', 3)
m4_define(`FUN', `eval(A + 2)')
#include <stdio.h>
#define STR(X) #X
int main() {
printf("%s", STR(FUN()));
}
preprocessed with m4 and compiled would output 5.
#include <stdio.h>
#include <string.h>
#define MAX_LENGTH 5
int main()
{
// specify format
char formatStr[20] = {0};
snprintf(formatStr, 20-1, "%s%d%s", "%", MAX_LENGTH-1, "s%u");
printf("%s\n", formatStr);
// example to use that format
char *input = "programming 123";
char dataStr[MAX_LENGTH] = {0};
int dataVal;
sscanf(input, formatStr, dataStr, &dataVal);
printf("%s-%d\n", dataStr, dataVal);
return 0;
}
output:
%4s%u
prog-21942

C macro with flexible argument

I need to do something like :
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#define INCR(count,ARGS...) \
if(ARGS) \
count++; \
void main()
{
int count =1;
int flag =1;
INCR(count);
printf("count %d",count);
INCR(count,flag); /* flag determines if the count is to be incremented or not */
printf("count %d",count);
}
I get following errors:
sh-4.3$ gcc -o main*.c
main.c: In function 'main':
main.c:6:8: error: expected expression before ')' token
if(ARGS) \
^
main.c:15:5: note: in expansion of macro 'INCR'
INCR(count);
^
sh-4.3$
Here the counter is supposed to be incremented only if the flag is present. I need a macro with flexible number of arguments. Please help me on this
Based on the example in https://stackoverflow.com/a/11763277/5085250 you can do something like this:
#define GET_MACRO(_1,_2,NAME,...) NAME
#define INCR(...) GET_MACRO(__VA_ARGS__, INCR2, INCR1)(__VA_ARGS__)
#define INCR1(count)\
count++;
#define INCR2(count,flag)\
if(flag)count++;
Here I assume you want to increment if no flag is given. If you don't want to increment in that case you need to modify the INCR1 part...

Add two macro and convert to string in pre-processing stage

I want to add two macro definition and want to convert result into string in pre-processing stage itself i tried it in following ways but it doesn't work
#include <stdio.h>
#define TO_STRING_IND(arg) #arg
#define TO_STRING(arg) TO_STRING_IND(arg)
#define ABC 1
#define XYZ 2
#define TOTAL (ABC+XYZ)
#define total_str TO_STRING(TOTAL)
int main()
{
printf("total %d \n",TOTAL);
printf("total_str %s \n",total_str);
return 0;
}
output of this program is as follows,
total 3
total_str (1+2)
I expect total_str to be 3 in string.
Any suggestions ?
You can in addition preprocessor in the range of up to 256(BOOST_PP_LIMIT_MAG) if You can use the boost.
#include <stdio.h>
#include <boost/preprocessor/arithmetic/add.hpp>
#define TO_STRING_IND(arg) #arg
#define TO_STRING(arg) TO_STRING_IND(arg)
#define ABC 1
#define XYZ 2
#define TOTAL (ABC+XYZ)
#define total_str TO_STRING(BOOST_PP_ADD(ABC, XYZ))
int main()
{
printf("total %d \n",TOTAL);
printf("total_str %s \n",total_str);
return 0;
}
The only place where the preprocessor does any calculation is in #if statements. Otherwise the preprocessor makes only textual replacements. Therefore it cannot be done in the preprocessor stage what you are trying to do.
(ABC+XYZ) this will be replaced by (1+2). Then the TOTAL in your Program will be replaced by (1+2).
so printf("total %d \n",(1+2)); this will add the number and gives the output as 3.
But total_str will be replaced by "(1+2)", where (1+2) is a string.
The reason is TO_STRING((1+2)) will be replaced by #(1+2). # is Stringizing operator. it will convert the argument to string.
printf("total_str %s \n","(1+2)"); it can't add (1+2) because it is a string.
so you will get the result as (1+2).

Automatically replacing variables with #defines

I have a file with about 100 #defines in it, from 1-100, and each with a unique string value.
Now I'm trying to print this value, but instead of the value, I want to print what the #define is. For example:
#define FIRST_VALUE 1
var = FIRST_VALUE;
printf("%s", var);
and I want the printf to print FIRST_VALUE, not 1.
Is there any way to do this in C? Or must I just write out 100+ case blocks inside a switch statement?
You can use stringification to achieve what you are looking for:
#define FIRST_MACRO
#define MACRO_TO_STRING(x) #x
#include <stdio.h>
main() {
printf("%s\n", MACRO_TO_STRING(FIRST_MACRO));
}
This program will output:
FIRST_MACRO
After talking to one of my TA's at school, we've decided that the best way to do this would be to write an AWK script to process the header file and automatically generate all the case statements needed.
Thanks guys!
You can't do exactly what you want, since by the time the compiler gets the pre-processor output, the "ONE" token is long gone. However, if your goal is to write the list of constants once but generate both tokens and strings, then this can be done.
First, use a macro to build the constants as enums in a header file. File enums.h:
#ifndef ENUMS_H
#define ENUMS_H
#ifndef ENUM
#define ENUM(name,val) enum { name = val };
#endif
ENUM(ONE,1)
ENUM(TWO,2)
ENUM(THREE,3)
#endif /* ENUMS_H */
Second, redefine the macro in a .c file to create a string/integer mapping and include the .h file in the right place. File enums.c:
#include
#include
typedef struct {
char *str;
int val;
} DescriptiveEnum;
static DescriptiveEnum enums[] = {
#define ENUM(name,val) { #name, val },
#include "enums.h"
};
#define NUM_ENUMS (sizeof(enums)/sizeof(enums[0]))
char *enum_to_str(int val)
{
int i;
for (i=0;i<NUM_ENUMS;i++) {
if (enums[i].val == val) return enums[i].str;
}
return "";
}
Now both the enum constants and the mapping function are available to callers. File main.c:
#include <stdio.h>
#include <stdlib.h>
#include "enums.h"
char *enum_to_str(int val);
int main(int argc, char *argv[])
{
int val;
val = ONE;
printf("%d %s\n",val,enum_to_str(val));
return EXIT_SUCCESS;
}

Resources