I have #define function with argument such as DEF_GLOBAL_STRUCT(index) and I need to call this macro from 1 to 100. What is the best way? Can I use for loop?
I made the simple code to show my problem.
#include <stdio.h>
#include <stdint.h>
#define DEF_GLOBAL_STRUCT(index) uint8_t m_##index##_size=2; \
uint32_t m_##index##_data1=0; \
uint32_t m_##index##_data2=0;
DEF_GLOBAL_STRUCT(1)
DEF_GLOBAL_STRUCT(2)
DEF_GLOBAL_STRUCT(3)
// ...
DEF_GLOBAL_STRUCT(100)
int main()
{
printf("%u\n", m_1_size);
return 0;
}
Instead of 100 lines of define function call, can I use something like for loop. Or is there any other solution?
If I have all the control of the code I can define structure and declare it with array. But I can't do it. I need to use this type of define function. That is my limitation.
Your question is asking if you can mix C language with Preprocessor directives to automate the generation of code using both C language and Preprocessor directives.
The answer is not in the way you are trying to do it because of how the Preprocessor and the C compiler work.
The Preprocessor is a separate step from compilation. The idea is that the Preprocessor does a text replacement step of the C source code file to generate a new, temporary version of the C source code file which is then compiled by the C compiler.
It is two different steps and first the Preprocessor does its work and then the C compiler does its work.
What I would suggest is to write a simple program that generates an include file that contains the list of definitions you want to use. Then in the place where you want to put those definitions, use the #include directive to include it at that point.
So if you have a simple script or perhaps a C program something like:
#include <stdio.h>
int main ()
{
int i;
for (i = 1; i <= 100; i++) printf ("DEF_GLOBAL_STRUCT(%d)\n", i);
return 0;
}
Then you compile it and run it from a command line redirecting the output as in:
mygen >junk.h
then in the place you need these directives:
#include <stdio.h>
#include <stdint.h>
#define DEF_GLOBAL_STRUCT(index) uint8_t m_##index##_size=2; \
uint32_t m_##index##_data1=0; \
uint32_t m_##index##_data2=0;
#include "junk.h"
int main()
{
printf("%u\n", m_1_size);
return 0;
}
You can save some typing by defining another macro:
#include <stdio.h>
#include <stdint.h>
#define DEF_GLOBAL_STRUCT(index) uint8_t m_##index##_size=2; \
uint32_t m_##index##_data1=0; \
uint32_t m_##index##_data2=0;
#define DEF_GLOBAL_STRUCT_DECADE(tens) \
DEF_GLOBAL_STRUCT(tens##0) \
DEF_GLOBAL_STRUCT(tens##1) \
DEF_GLOBAL_STRUCT(tens##2) \
DEF_GLOBAL_STRUCT(tens##3) \
DEF_GLOBAL_STRUCT(tens##4) \
DEF_GLOBAL_STRUCT(tens##5) \
DEF_GLOBAL_STRUCT(tens##6) \
DEF_GLOBAL_STRUCT(tens##7) \
DEF_GLOBAL_STRUCT(tens##8) \
DEF_GLOBAL_STRUCT(tens##9)
DEF_GLOBAL_STRUCT(1)
DEF_GLOBAL_STRUCT(2)
DEF_GLOBAL_STRUCT(4)
DEF_GLOBAL_STRUCT(5)
DEF_GLOBAL_STRUCT(6)
DEF_GLOBAL_STRUCT(7)
DEF_GLOBAL_STRUCT(8)
DEF_GLOBAL_STRUCT(9)
DEF_GLOBAL_STRUCT_DECADE(1)
DEF_GLOBAL_STRUCT_DECADE(2)
DEF_GLOBAL_STRUCT_DECADE(3)
DEF_GLOBAL_STRUCT_DECADE(4)
DEF_GLOBAL_STRUCT_DECADE(5)
DEF_GLOBAL_STRUCT_DECADE(6)
DEF_GLOBAL_STRUCT_DECADE(7)
DEF_GLOBAL_STRUCT_DECADE(8)
DEF_GLOBAL_STRUCT_DECADE(9)
DEF_GLOBAL_STRUCT(100)
int main()
{
printf("%u\n", m_1_size);
return 0;
}
Related
Is there any idea to pass C string as part of the defined macro like below code?
#define AAA_NUM 10
#define BBB_NUM 20
#define PREFIX_NUM(string) string##_NUM
int main()
{
char *name_a = "AAA";
char *name_b = "AAA";
printf("AAA_NUM: %d\n", PREFIX_NUM(name_a));
printf("BBB_NUM: %d\n", PREFIX_NUM(name_b));
return 0;
}
Expected output
AAA_NUM: 10
BBB_NUM: 20
As mentioned in other posts, you can't use run-time variables in the pre-processor. You could however create enum that way. Though it is usually not a good idea to generate identifiers with macros either, save for special cases like when maintaining an existing code base and you are limited in how much of the existing code you can/want to change. So it should be used as a last resort only.
The least bad way to write such macros would be by using a common design pattern called "X macros". These are used when it is important that code repetition should be reduced to a single place in the project. They tend to make the code look rather alien though... Example:
#define PREFIX_LIST(X) \
/* pre val */ \
X(AAA, 10) \
X(BBB, 20) \
X(CCC, 30) \
enum // used to generate constants like AAA_NUM = 10,
{
#define PREFIX_ENUMS(pre, val) pre##_NUM = (val),
PREFIX_LIST(PREFIX_ENUMS)
};
#include <stdio.h>
int main (void)
{
// one way to print
#define prefix_to_val(pre) pre##_NUM
printf("AAA_NUM: %d\n", prefix_to_val(AAA));
printf("BBB_NUM: %d\n", prefix_to_val(BBB));
// another alternative
#define STR(s) #s
#define print_all_prefixes(pre, val) printf("%s: %d\n", STR(pre##_NUM), val);
PREFIX_LIST(print_all_prefixes)
return 0;
}
A macro is only processed before compilation and not at runtime. Your code example does not work as you can see here.
Good practice (for example MISRA coding rules) recommend to use macros as little as possible since it is error prone.
Preprocessor works at compile time and here name_a and name_b are non constant, and even if they were (i.e. const char *str is a real constant in C++ but not in C), there is a literal substitution and the preprocessor does not know the contents of variables.
This works (notice that the parameter should be expanded by another macro in order to get a valid token):
#include <stdio.h>
#define AAA_NUM 10
#define BBB_NUM 20
#define _PREFIX_NUM(string) string##_NUM
#define PREFIX_NUM(string) _PREFIX_NUM(string)
int main(void)
{
#define name_a AAA
#define name_b BBB
printf("AAA_NUM: %d\n", PREFIX_NUM(name_a));
printf("BBB_NUM: %d\n", PREFIX_NUM(name_b));
return 0;
}
There is no way in C to create runtime symbols and use them. C is a compiled language and all symbols have to be known before the compilation.
The preprocessor (which do changes on the text level before the compilation) does not know anything about the C language.
Is it possible to write:
#define FIRST_DEF 1
#define SECOND_DEF 2
#ifndef ALREADY_DEFINED
#define MY_MACRO FIRST_DEF
#define ALREADY_DEFINED
#else
#define MY_MACRO SECOND_DEF
#endif
So that MY_MACRO does not have the same value when not used the first time?
So that writting:
int a = MY_MACRO;
int b = MY_MACRO;
expands to:
int a = 1;
int b = 2;
If not, is there a way to do this?
(I know that this example is silly but it is just to make the question clearer.)
For your example, you can use the pre-defined macro __COUNTER__ which will get incremented everytime it is used. Note that it is a non-standard compiler extension, but both GCC and MSVC support it.
Yes. I think it is OK.
#include "xxx.h"
// FIRST_DEF here
#include "xxx.h"
// SeCOND_DEF here
But you must include the header twice
Please,
could you tell me what does the code below do?
...code...
#include file.h
...code...
I was used to put includes a the beggining of each file. I have never seen this before and also wasn't able to find anything in the internet.
#include is a pre-processor directive that takes the file given as the argument and dumps its contents in the current file. Typically, this is used to include definitions of commons functions from header files, but there's no necessity to use it in that way.
It's usage is not limited to the starting of the file, but note that the variables, macros or functions declared in this header will not be usable before the include statement even if on the same file.
As everyone tells you #include can be used every where (provided it is on its own logicial line). And there are cases where you want to #include several times the same file. Read first the X macro wikipage, and the C preprocessor wikipage.
And I have a concrete example in my MELT monitor (related to MELT ...).
I have a predef-monimelt.h (generated) file containing lines like
MOM_PREDEFINED_NAMED( name, id,hash) e.g.
MOM_PREDEFINED_NAMED(GET,_9dsak0qcy0v_1c5z9th7x3i,1573018885)
MOM_PREDEFINED_NAMED(HEAD,_47fatww79x6_vh8ap22c0ch,3922245622)
MOM_PREDEFINED_NAMED(web_handler,_7sav6zery1v_24sa6jwwu6c,2339220870)
#undef MOM_PREDEFINED_NAMED
My monimelt.h file (a real header file) define external pointers and an enum, so has notably:
// declare the predefined
#define MOM_PREDEFINED_NAMED(Name,Id,H) extern momitem_t* mom_named__##Name;
#include "predef-monimelt.h"
/// declare the hash of the predefined as an enum
#define MOM_PREDEFINED_NAMED(Name,Id,H) mom_hashname__##Name = H,
enum {
#include "predef-monimelt.h"
};
My main.c file contains notably a routine :
// if this routine is compiled, we are sure that all predefined hashes
// are unique
const momitem_t *
mom_predefined_item_of_hashcode (momhash_t h) {
switch (h) {
#define MOM_PREDEFINED_NAMED(Nam,Id,Hash) case Hash: return mom_named__##Nam;
#include "predef-monimelt.h"
default:
return NULL;
}
}
but my items.c includes the predef-monimelt.h file twice (to create the predefined items at initialization, and to define their variables):
void mom_create_predefined_items (void) {
int nbnamed = 0;
#define MOM_PREDEFINED_NAMED(Nam,Id,H) do { \
mom_named__##Nam = mom_make_item_of_identcstr(#Id); \
mom_named__##Nam->i_space = momspa_predefined; \
mom_register_item_named_cstr (mom_named__##Nam, #Nam); \
nbnamed ++; \
} while(0);
#include "predef-monimelt.h"
} // end of mom_create_predefined_items
// declare the predefined
#define MOM_PREDEFINED_NAMED(Nam,Id,H) momitem_t* mom_named__##Nam;
#include "predef-monimelt.h"
FWIW, the MELT monitor is GPLv3+ licensed software
I'm looking for a creative solution for making sure that variables delivered to a specific macro are declared with type volatile in C language, with TMS470 compiler. meaning:
good method:
volatile int *_p_reg;
VOLATILE_MACRO(_p_reg);
compilation failure:
int *_p_reg;
VOLATILE_MACRO(_p_reg);
I wish to perform the verification after the compilation, meaning going over the disassembly or the debug information and identify those calls.
I can't seem to find any evidence for the volatile in the debug info.
any ideas?
thanks!
I wouldn't expect there to be any, but of course it's totally up to the compiler.
You could of course re-architect it so that the macro does the whole definition, i.e.
#define VOLATILE_MACRO(t, p) volatile t p
and use it like:
VOLATILE_MACRO(int, _p_reg);
but of course that might not work for you.
Two possible solutions using gcc extensions. The run-time version uses __builtin_types_compatible_p and an assert. The compile-time version is similar but uses a hack to get a static assert which fires at compile-time (albeit with a rather cryptic error message):
Run-time
#include <stdio.h>
#include <assert.h>
#define VOLATILE_MACRO(p) \
assert (__builtin_types_compatible_p(typeof(p), typeof(volatile int *)))
int main()
{
volatile int * x;
int * y;
VOLATILE_MACRO(x); // <<< OK
VOLATILE_MACRO(y); // <<< run-time error
return 0;
}
Compile-time
#include <stdio.h>
#include <assert.h>
#define A BUILD_NAME(__LINE__)
#define BUILD_NAME(line) BUILD_NAME2(line)
#define BUILD_NAME2(line) assert_ ## line
#define STATIC_ASSERT(test) typedef char A[(test) ? 1 : -1]
#define VOLATILE_MACRO(p) \
STATIC_ASSERT (__builtin_types_compatible_p(typeof(p), typeof(volatile int *)))
int main()
{
volatile int * x;
int * y;
VOLATILE_MACRO(x); // <<< OK
VOLATILE_MACRO(y); // <<< compile error
return 0;
}
Note that if you need to support other volatile types then the macro can simply be extended with multiple chained __builtin_types_compatible_p tests, e.g.
#define VOLATILE_MACRO(p) \
assert (__builtin_types_compatible_p(typeof(p), typeof(volatile int *)) ||
__builtin_types_compatible_p(typeof(p), typeof(volatile short *)))
I want to define a constant depending on the OS in use.
As such:
#include <stdio.h>
#ifdef _Win32 //Used for system("cls") command
#include <process.h>
#define CLEAR "system(\"cls\")"
#endif
#ifdef __APPLE__
#define CLEAR "system(\"clear\")"
#endif
int main()
{
CLEAR;
}
Xcode gives me an error stating that expression result unused at
#define CLEAR "system(\"clear\") and inside the main function.
I am on a Mac.
Use:
#define CLEAR system("clear")
not
#define CLEAR "system(\"clear\")"
You get the error because your macro call is substituted with:
"system(\"clear\")";
which is a useless expression statement (the expression being the string here) like for example:
0; // valid but pointless
try altering your main function as such:
int main()
{
int rc;
rc = CLEAR;
return rc;
}
You need to catch the return value of the system() call and use it
#define CLEAR system("clear")
and not
#define CLEAR "system(\"clear\")"
The compiler will create a new C code (called pre-processor code) in which will replace the macro name by its content.
so if you define macro in this way:
#define CLEAR "system(\"clear\")"
You will get in the new code (pre-processor code) generated by the Compiler:
int main()
{
"system(\"clear\")";
}
You can see the code generated by the compiler (pre-processor code) with gcc -E