I have following code:
#include <stdio.h>
#ifdef COMP_DEF
static const char * x = COMP_DEF;
#else
static const char * x = "NULL";
#endif
int main(int argc, char ** argv)
{
printf("%s\n", x);
return 0;
}
What I want is to compile this program with two ways. First with compiler parameter:
-DCOMP_DEF=FOO_BAR
and second way without this. I expect, my program would print FOO_BAR and NULL.
But when I try to compile I get following errors:
:0:10: error: 'FOO_BAR' undeclared here
(not in a function) main.c:5:25: note: in expansion of macro
'COMP_DEF' static const char * x = COMP_DEF;
Is it possible to print/store in variable compiler passed macrodefine value?
You should try this common trick usually called stringification:
#define STR_IMPL(x) #x
#define STR(x) STR_IMPL(x)
#ifdef COMP_DEF
static const char * x = STR(COMP_DEF);
#else
static const char * x = "NULL";
#endif
# followed by argument name in macro expands to string literal containing passed argument. If you do just
#define STR(x) #x
this would make STR(COMP_DEF) expand to "COMP_DEF". To avoid this you need another level of macro expansion.
Related
As described in the title, I want to concatenate the content of string var with string using Macro.
This is an example:
const char * Name = "OverFlow"
#define DEFINE_VAR(str) unsigned char u8_##str##_Var;
I want to use the macro as following:
DEFINE_VAR(Name)
The result is:
unsigned char u8_Name_Var;
and not
unsigned char u8_OverFlow_Var;
Do you have any idea?
The preprocessor cannot concatenate the value of a variable with a string it can only concatenate preprocessor tokens that may be the result of a macro expansion.
It would be possible with #define Name OverFlow or similar.
Example file macro.c:
Edit: As suggested by Lundin I added macros to get a string literal in case the variable char *Name = "OverFlow"; is needed for other purposes.
#define NAME OverFlow
#define DEFINE_VAR_2(str) unsigned char u8_##str##_Var
#define DEFINE_VAR(str) DEFINE_VAR_2(str)
/* macros to get a string literal */
#define STR_2(x) #x
#define STR(x) STR_2(x)
#define STRNAME STR(NAME)
#define STRVAR const char *Name = STR(NAME)
/* this works */
DEFINE_VAR(NAME);
/* this doesn't work */
DEFINE_VAR_2(NAME);
/* if you need a string with the variable name */
const char *Name = STRNAME;
/* or with a single macro */
STRVAR;
Result:
# 1 "macro.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "macro.c"
/* macros to get a string literal as proposed by Lundin */
/* this works */
unsigned char u8_OverFlow_Var;
/* this doesn't work */
unsigned char u8_NAME_Var;
/* if you need a string with the variable name */
const char *Name = "OverFlow";
/* or with a single macro */
const char *Name = "OverFlow";
Ok, here's something that works but may not be what you are looking for exaclty
and the gnu documentation link for you to understand C preprocessor
main.c
#include <stdio.h>
#define xstr(s) str(s)
#define str(s) "u8_"#s"_Var"
int main(int argc, char const *argv[])
{
const char *Overflow;
printf("name: %s\n", Overflow);
printf("defined: %s\n", xstr(Overflow));
return 0;
}
output
name: (null)
defined: u8_Overflow_Var
https://gcc.gnu.org/onlinedocs/cpp/Stringizing.html
&
https://gcc.gnu.org/onlinedocs/cpp/Concatenation.html#Concatenation
The define works, what are you trying to achieve ?
const char * Name = "OverFlow";
#define DEFINE_VAR(str) unsigned char u8_##str##_Var;
DEFINE_VAR(Name)
int main(int argc, char const *argv[])
{
printf("%s\n", Name);
return 0;
}
output result is
OverFlow
So, I am familiar with nested macros.
Now, I want to change a macro first changed by _Generic with some other macro like:
#include<stdio.h>
#define some_func(X) _Generic((X), \
char* : some_func_char, \
default : some_func_default)(X)
#define some_func_char(X) some_func_char(X, sizeof(X)/ sizeof(char))
void (some_func_char)(char *blah, size_t len_blah)
{
// do something
}
void some_func_default(double blah)
{
// code
}
int main()
{
some_func("hello");
return 0;
}
but it is raising a error as
main.c: In function ‘main’:
main.c:5:22: error: too few arguments to function ‘some_func_char’
5 | #define some_func(X) _Generic((X), \
| ^~~~~~~~
main.c:22:3: note: in expansion of macro ‘some_func’
22 | some_func("hello");
| ^~~~~~~~~
main.c:10:7: note: declared here
10 | void (some_func_char)(char *blah, size_t len_blah)
| ^~~~~~~~~~~~~~
some_func_char is calling the function not the macro in the _Generic call (even trying to stop the expansion with the parenthesis), on the other hand, you can not ommit the second parameter in some_func_default if some_func_char expects two parameters, switch to:
#include <stdio.h>
#define some_func(X) _Generic((X), \
char *: some_func_char, \
default: some_func_default)(X, sizeof X)
void some_func_char(char *blah, size_t len_blah)
{
// do something
}
void some_func_default(double blah, size_t dummy)
{
(void)dummy;
// code
}
int main()
{
some_func("hello");
return 0;
}
or better yet:
#include <stdio.h>
#include <string.h>
#define some_func(X) _Generic((X), \
char *: some_func_char, \
default: some_func_default)(X)
void some_func_char(char *blah)
{
size_t len = strlen(blah);
// do something
}
void some_func_default(double blah)
{
// code
}
int main()
{
some_func("hello");
return 0;
}
This second version allows you to pass and compute the correct length also for a pointer to char, don't worry for the performance, strlen is very fast.
Also, notice that sizeof(char) is always 1
It is important to understand that although generic selection is not really useful except in conjunction with macros, it is not itself interpreted by the preprocessor. Consider, then, this statement:
some_func("hello");
Where that appears in the example code, a definition of some_func as the identifier of a function-like macro is in scope, and the expansion of that macro produces this, prior to rescanning:
_Generic(("hello"), char *: some_func_char, default: some_func_default)("hello")
The preprocessor then scans that for further macro replacements, but again, _Generic is not a macro, and it has no other special significance to the preprocessor. There is an in-scope definition of some_func_char as the identifier of a function-like macro, but the appearance of that identifier in the above line does not match it because it is not followed by an open parenthesis. Nothing else in that line is significant (in context) to the preprocessor either, so that's in fact the final preprocessed form.
Now observe that the expression ("hello") matches the char * alternative of the generic selection expression, so the function identifier some_func_char is the selected result, but the parenthesized argument list ("hello") does not contain the correct number of arguments for that function. The overall expression is a more complicated variation on trying to call (some_func_char)("hello"). The some_func_char() macro never comes into play.
It should be clear, now, that you cannot use generic selection to select function identifiers of functions that take different numbers of arguments. But of course you can use it to select different function calls. For example,
#define some_func(X) _Generic( \
(X), \
char *: some_func_char((X), sizeof (X)), \
default: some_func_default(X) \
)
void some_func_char(char *s, size_t z) { }
void some_func_default(void *p) { }
int main(void) {
some_func("hello");
}
I am trying to create a macro in c, that will take a variable name, and declare it. I could call it like this:
MY_MACRO(test);
Would produce:
int test;
In order to achieve this I went this way:
#define MY_MACRO(var) /
int ##var; /
But the compiler doesn't understand this. Does such syntax exist in C11?
I wouldn't recommend doing such a thing. Anyway, there are two problems. First of all, to skip a newline, you need \, not /.
Second, the ## is wrong. What it does is concatenating the var to the int. So with MY_MACRO(foo) you would get intfoo;, but you want int foo;
The macro needs to be like this:
#define MY_MACRO(var) \
int var
## is not applicable here as it concatenates the token with something else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MY_MACRO(var) int var
or
#define MY_MACRO(var) \
int var \
void foo(void)
{
MY_MACRO(a);
a = rand();
printf("%d\n",a);
}
## pastes two tokens together into one token.
#define poem(var)\
int jack##var;
// Produces 'int jacksprat;'
poem(sprat)
In your case you don't need to do anything special at all, you can just use the argument directly:
#define MY_MACRO(var)\
int var;
The correct syntax would be something along the lines of this:
#define MY_MACRO(ident) \
int ident
int main() {
MY_MACRO(test);
test =42;
return test;
}
However, have you been looking into typedefs? Unlike typedefs, macros are considered bad practice.
I'm trying to assign data type to world but unable to figure it out.
#include <stdarg.h>
#include <stdio.h>
#define TRACE(arg) TraceDebug arg ;\
void TraceDebug(const char* format, ...);
void TraceDebug(const char* format, ...)
{
char buffer[256];
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
}
int main(void)
{
int a =55;
TRACE((Hello,a));
return 0;
}
Below is the error statement in detail.
main.c: In function 'main':
main.c:28:12: error: 'Hello' undeclared (first use in this function)
TRACE((Hello,a));
^
main.c:13:32: note: in definition of macro 'TRACE'
#define TRACE(arg) TraceDebug arg ;\
^
main.c:28:12: note: each undeclared identifier is reported only once for each function it appears in
TRACE((Hello,a));
^
main.c:13:32: note: in definition of macro 'TRACE'
#define TRACE(arg) TraceDebug arg ;\
^
Is there anyway possible to declare Hello as a variable, after declaring I need to get the address of the variable.
In simple I want to change the below code into a variadic function arguments
for example #define QU(arg1,arg2) as #define QU(arg1,...) since variadic macro is not supported am using variadic functions.
#define TRACE(arg1) QU arg1
#define QU(arg1,arg2) {static const char arg1; \
printf("%p\n",(void*)&arg1);\
printf("%d\n",arg2);}\
int main(void)
{
int aaa =333;
int bbb =444;
TRACE((Hello,aaa));
TRACE((Hello2,bbb));
return 0;
}
1) (title) How to declare the data type for variable arguments?
2) (1st question) I'm trying to assign data type to world but unable to figure it out.
1) The data type for the variadic argument (represented by the ellipses: ... ) is always the type of the variable preceding the ellipses . For this prototype:
int variadicFunc(int a, const char *b, ...);
^^^^^^^^^^ ^^^
type assumes the type const char *
2) From content of your question only, the answer could be to be use a typedef statement:
typedef char World; // a new type 'World' is created
But there are clarifications in the comments:
if i change the string to variable i can reduce the memory size,... (you)
You want to have a variable argument list to pass variables existing in your program that you want to place on a Trace list for debugging
purposes. (is that close?)... (me)
(is that close?) yes, that's the thing am trying to do... Are you always going to pass the same type to this function? Ahh, type will
be like TRACE(("Hello", a,"world")); (you)
It appears you want to enter a variable number of either string literals, or string variables as function arguments, then for those items to be placed into variables, then the addresses of those variables to be stored in a file, for the purpose of saving space.
The following code illustrates how you can pass a variable number of strings (in different forms) into a function, and have the address and content retained into a struct. From this, you should be able to adapt from what I have done here, to something more useful to your needs. Note, I have reserved the first string argument to be used a file location to store addresses.
#define MAX_LEN 200
typedef struct {
unsigned int addr;
char str[MAX_LEN];
} DATA;
int variadicFunc(int argCount, const char *str, ...);
int main(void)
{
char a[] = {"this is a string"};
char b[] = {"another string"};
char c[] = {"yet another string"};
// count non-variable v1 v2 v3 v4
variadicFunc(4, ".\\storage.txt", a, b, "var string", c);
// ^count of variable argument list
return 0;
}
int variadicFunc(int argCount, const char *str, ...)
{
va_list arg;
int i;
char sAddr[10];
DATA *d = calloc(argCount, sizeof(*d));
va_start(arg, str);
FILE *fp = fopen(str, "w");//using first string as filename to populate
if(fp)
{
for(i=0;i<argCount;i++)
{
// retain addresses and content for each string
strcpy(d[i].str, va_arg(arg, const char *));
d[i].addr = (unsigned int)&d[i].str[i];
sprintf(sAddr, "%X\n", d[i].addr);
fputs(sAddr, fp);
}
fclose(fp);
}
return 0;
}
In c I have the following in an existing code base:
#define MYVAR (1)
As you can see this is conforming good practices in C by surrounding the #define with parenthesis (even though I know in this case it makes no difference since the value is not
an expression). Regardless I would like to use this in stringification. when I do this:
#define STRINGIFY(x) #x
#define TO_STRING(x) STRINGIFY(x)
const char* mystring = TO_STRING(MYVAR) ;
The resultant string is "(1)". I'd like to eliminate the parentheses without doing the simple:
#define MYVAR 1
Is there anyway to eliminate parentheses during stringification in c?
Just use STRINGIFY x instead of STRINGIFY(x)
#include <stdio.h>
#define MYVAR 1
#define STRINGIFY(x) #x
#define TO_STRING(x) STRINGIFY x
int main(void)
{
const char *mystring = TO_STRING(MYVAR);
printf("%s\n", mystring);
return 0;
}
TO_STRING(x) expands to STRINGIFY (1) when MYVAR is defined as (1)
If MYVAR is defined as 1 without parentheses you get a compile time error.