Sample code:
main()
{
printf("%d\n", MARCO);
// printf("%s\n", MARCO);
}
When I try to use gcc -D option, I found the following command works:
gcc -D MARCO=12345 test.c
but when I change 12345 to a string:
gcc -D MARCO=abcde test.c
an error occurs:
error: ‘abcde’ undeclared (first use in this function)
I have tried -DMARCO=abcde, -DMARCO="abcde", -D MARCO="abcde"; all failed with that error.
Does this -D option only support integers?
The trouble is that double quotes are recognized by the shell and removed, unless you prevent the shell from doing so by escaping the double quotes (with backslashes) or enclosing them in single quotes (which is what I'd use):
gcc -DMARCO='"abcde"' test.c
The single quotes are stripped by the shell but that means that the double quotes are seen by the C preprocessor. You need to use the %s format, of course.
By changing the macro, you can stringify a non-quoted name on the command line:
#include <stdio.h>
#define STRINGIFY(x) #x
#define MACRO(x) STRINGIFY(x)
int main(void)
{
printf("%s\n", MACRO(MARCO));
return(0);
}
Compile that with gcc -o testprog -DMARCO=abcde test.c and you will find it produces the correct answer.
you can also use like this...
-DMACRO="\"abcde\""
Ref:
How do I pass a quoted string with -D to gcc in cmd.exe?
The macro MARCO is literally replaced by the string you entered and only then is the code compiled. Since there are no quotes around the string (the double quotes in two of the examples are interpreted as delimiters by the shell), the abcde is not interpreted as a string, but as an identifier. Since it isn't defined, the code fails to compile.
Related
How to use a variable from a batch file and send the value to a variable in a C file/program?
I absolutely do not know how to do this, and I don't know if it is even possible.
I am thinking about something like this:
Batch file:
#echo off
set name= %1
::somehow set a variable in myfile.c to "name"'s value
gcc myfile.c -o readf
.\readf
C file:
#include <stdio.h>
int main() {
char(or any other) name[] = /* the value of "name" in the batch file */
printf(name);
return 0;
}
As pointed out by #kopecs, it seem that you want to define a macro in the command line while compiling your code. This would be useful if you want to define some constant that will be included in the binary for future execution, but not if you simply want to get argument from the command line.
Modify your code the following way to use the preprocessor
#include <stdio.h>
#ifndef VARIABLE
// In case you want to define a default value for your VARIABLE
#define VARIABLE "default value"
#endif
int main() {
char(or any other) name[] = VARIABLE // VARIABLE is a preprocessing macro that will be defined by the compiler
printf(name);
return 0;
}
Then invoke the compiler with the following preprocessor option
#echo off
set name=%1
::somehow set a variable in myfile.c to "name"'s value
gcc myfile.c -o readf -D "VARIABLE=%name%" -Wall -Wextra -pedantic
.\readf
Documentation quote for the argument
-D name=definition
The contents of definition are tokenized and processed as if they appeared during translation phase three in a ‘#define’ directive. In particular, the definition is truncated by embedded newline characters.
If you are invoking the preprocessor from a shell or shell-like program you may need to use the shell’s quoting syntax to protect characters such as spaces that have a meaning in the shell syntax.
If you wish to define a function-like macro on the command line, write its argument list with surrounding parentheses before the equals sign (if any). Parentheses are meaningful to most shells, so you should quote the option. With sh and csh, -D'name(args…)=definition' works.
-D and -U options are processed in the order they are given on the command line. All -imacros file and -include file options are processed after all -D and -U options.
However, I would recommend using command line argument for your program, that would be more flexible and avoid to recompile it each time you want to change it (unless you want to redistribute the binary with the hardcoded string).
#include <stdio.h>
int main(int argc, char* argv[]) {
// add some sanity checking against argc before getting the value in argv
char(or any other) name[] = argv[1];
printf(name);
return 0;
}
and after compiling your code the with
gcc myfile.c -o readf -Wall -Wextra -pedantic
Just invoke with
.\readf name_value
The purpose of this is to build a program with command line-injected macros, using a Makefile.
I would like to define macros using multiple terms, however I am given an error as subsequent parts of the string are treated as files by gcc.
An example of what I need is as follows:
#define ULL unsigned long long
#define T_ULL typedef unsigned long long ull_t
As a result, I am only able to create macros that contain 1 term per definition.
The latter attempt allows me to create parameterized macros, however those are also limited to 1 term per definition.
Attempted solution
#include <stdio.h>
#define _STRINGIZE(x) #x
#define STRINGIZE(x) _STRINGIZE(x)
int main(void)
{
# ifdef DEBUG
# ifdef STRING
printf("%s", "A STRING macro was defined.\n");
printf("string: %s\n", STRINGIZE(STRING));
# else
printf("%s\n", "A DEBUG macro was defined.");
# endif
# endif
}
Results
As described by the man page, under the -D option description.
$ gcc define.c -D='DEBUG' ; ./a.out
A DEBUG macro was defined.
As described by this answer, as an alternative approach.
$ gcc define.c -D'DEBUG' ; ./a.out
A DEBUG macro was defined.
$ gcc define.c -D'DEBUG' -D'STRING="abc"' ; ./a.out
A STRING macro was defined.
string: "abc"
$ gcc define.c -D'DEBUG' -D'STRING="abc efg"' ; ./a.out
clang: error: no such file or directory: 'efg"'
A STRING macro was defined.
string: "abc"
$ gcc define.c -D'DEBUG' -D'STRING="abc efg hij"' ; ./a.out
clang: error: no such file or directory: 'efg'
clang: error: no such file or directory: 'hij"'
A DEBUG macro was defined.
string: "abc"
You don't need the STRINGIZE macro. The correct command-line syntax is:
gcc -DDEBUG -DSTRING='"abc def"' program.c
In other words, you need to quote the whole value of the defined macro, including C string delimiters (").
Then you can just do:
printf("string: %s\n", STRING);
I want to compile a c program under different names. In the main file, I have the following macro:
#ifndef EXECUTABLE_NAME
#define EXECUTABLE_NAME "defaultname"
#endif
When compiling using gcc, I use -D switch to define this macro (is that the right term?):
$ gcc main.c -DEXECUTABLE_NAME="newname"
I do not know if the -D works fine or not because when I try to do something like the code below...it fails...I can not tell if the -D switch is screwing up or the syntax of using the macro inside the printf() function is not correct:
printf("no or invalid arguments. usage: %s [0,255]\n", EXECUTABLE_NAME);
I get this error:
main.c:48:57: note: in expansion of macro ‘EXECUTABLE_NAME’
printf("no or invalid arguments. usage: %s [0,255]\n", EXECUTABLE_NAME);
Any suggestions?
It works, and you can see that because of the error. Which by the way is because you're defining your macro wrong on the command line, this is how you quote a string in a macro:
$ gcc main.c -DEXECUTABLE_NAME='"newname"'
And this said, it's not even needed. The executable path is always your first argument: *argv.
I tried this program with an integer, which is as follows
#ifndef EXECUTABLE_NAME
#define EXECUTABLE_NAME 2
#endif
int main()
{
printf("%d",EXECUTABLE_NAME);
}
and then typed gcc main.c -DEXECUTABLE_NAME=1 and it works as the value changes to 1. Is it a problem with the data type 'string' that you are using?
My configure.in file has:
VAR=yo
AC_SUBST(VAR)
Makefile.am has:
bin_PROGRAMS = hello
hello_SOURCES = hello.c
hello_CFLAGS =-DVAR=#VAR#
C file is:
#include <stdio.h>
int main()
{
printf("%s\n",VAR);
return 0;
}
When I do 'make install' there is error
Making install in src
make[1]: Entering directory `/home/albertpod/hello/src'
if gcc -DPACKAGE_NAME=\"hello\" -DPACKAGE_TARNAME=\"hello\" -DPACKAGE_VERSION=\"1.0\" -DPACKAGE_STRING=\"hello\ 1.0\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DPACKAGE=\"hello\" -DVERSION=\"1.0\" -I. -I. -DVAR=yo -g -O2 -MT hello-hello.o -MD -MP -MF ".deps/hello-hello.Tpo" -c -o hello-hello.o `test -f 'hello.c' || echo './'`hello.c; \
then mv -f ".deps/hello-hello.Tpo" ".deps/hello-hello.Po"; else rm -f ".deps/hello-hello.Tpo"; exit 1; fi
hello.c: In function ‘main’:
hello.c:8:13: error: ‘yo’ undeclared (first use in this function)
hello.c:8:13: note: each undeclared identifier is reported only once for each function it appears in
make[1]: *** [hello-hello.o] Error 1
make[1]: Leaving directory `/home/albertpod/hello/src'
make: *** [install-recursive] Error 1
So name of VAR becomes yo, but it is undeclared. My goal is to print yo, but how to solve this case?
I'm assuming you want the program to deliver the output
yo
Proper Quoting in configure.in
You also probably noticed that you are missing quotes, to make the replacement text of the define VAR a string literal. The difficulty is that you are passing this value through two instances of the shell that will strip quotes: the one that executes configure and the one that is invoked by make to run the compiler. So you need three levels of quoting, with appropriate escaping:
VAR="\"\\\"yo\\\"\""
AC_SUBST(VAR)
(You can try using single quotes in there to reduce the number of \, but it will probably become even more ugly.)
Proper Quoting in Makefile.am
You can also do the quoting in Makefile.am. This is especially useful if you need the value of VAR in the Makefile for other purposes too. You need two levels of qoutes, one to make the value a string literal and one that gets eaten by the shell:
hello_CFLAGS =-DVAR='"#VAR#"'
This works even if VAR contains (single) spaces or other funny characters, the only problematic characters are ', ", and \.
Stringification
Alternatively you can let the preprocessor add the quotes using the stringify operator #:
#include <stdio.h>
#define STR2(arg) #arg
#define STR(arg) STR2(arg)
int main()
{
printf("%s\n",STR(VAR));
return 0;
}
The indirection in the macros is necessary due to a quirk how the # operator works. If you would only use one level of macros, the output would be VAR.
Of course, this only works as long as the value does not contain any funny characters, like spaces.
Using AC_DEFINE
With AC_DEFINE it is slightly easier to define VAR to a value surrounded by quotes. Use
AC_DEFINE([VAR], ["yo"])
in configure.in and remove hello_CFLAGS =-DVAR=#VAR# from Makefile.am. Alternatively, if you need to compute the value of VAR in configure, use
VAR=yo
AC_DEFINE_UNQUOTED([VAR], ["$VAR"])
which will interpret shell substitutions in the value.
In both cases, you don't have access to VAR in the Makefile.
I'm trying to define a string macro before compiling my C code. I've tried something like:
#include <stdio.h>
int main(void) {
printf("%s", AMEM);
return 0;
}
and I've tried to compile with:
gcc -D AMEM="Deus Abencoa" file.c
But I keep getting this message:
file.c:5:15: note: in expansion of macro ‘AMEM’
printf("%s", AMEM);
^
<command-line>:0:4: note: each undeclared identifier is reported only once for each function it appears in
file.c:5:15: note: in expansion of macro ‘AMEM’
printf("%s", AMEM);
Any idea of how to put it to work?
Your shell interprets (“eats up”) the double-quotes. Since they need to be part of the cpp macro (as the C compiler requires them to form a string), you must pass them to the compiler driver, which means escaping them from the shell. Try this:
gcc -D'AMEM="Deos Abencoa"' file.c
Or this (commonly seen with GNU autoconf):
gcc -DAMEM=\"Deos\ Abencoa\" file.c
Do note that there is no space after -D either.
gcc -D AMEM='"Deus Abencoa"' file.c
The shell removes the single quotes, leaving the double quotes visible to the compiler. Before, the shell removed the double quotes.