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.
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
I've been working on a piece of code that had an overlooked derp in it:
#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
#define MAX_N_LENGTH
/*function prototypes*/
int main(){
...
}
It should be easy to spot with the context removed: #define MAX_N_LENGTH should have read #define MAX_N_LENGTH 9. I have no idea where that trailing constant went.
Since that macro was only used in one place in the form of char buf[ MAX_N_LENGTH + 1], it was extremely difficult to track down and debug the program.
Is there a way to catch errors like this one using the gcc compiler?
You can use char buf[1 + MAX_N_LENGTH], because char buf[1 +] should not compile with the error message error: expected expression before ']' token:
http://ideone.com/5m2LYw
What you have there isn't an undefined macro. It's an empty macro. And defined empty macros are perfectly legit, because you can test for their definedness.
They're used quite a lot in the implementation header files, although all those empty macros will be in the implementation namespace, which means they will either contain two underscores or an underscore followed by an uppercase letter.
What you could do is test whether you have an empty macro that's not in the implementation namespace, and you can do that with:
cpp -dM YOUR_FILE.c |
cut -d\ -f2- | grep '^[a-zA-Z0-9_]* $' |grep -v -e __ -e ^_[A-Z]
For your example, it should output just MAX_N_LENGTH.
It's not possible to catch this error in the general sense, because it isn't an error. There's plenty of cases where this sort of behavior is desired, so the compiler cannot treat it as an error or a warning.
If you can track the error down to a line, using gcc's -E command line argument will cause it to output the result of the preprocessor. In that case, your char line would have turned to char buf[+1], which is legal C code, but might catch your attention because you expected it to be char buf[9+1]. -E causes gcc to print those results, so you would actually see char buf[+1] in the output of gcc.
Issues like this are why C++ discourages use of define macros in this way (C++, of course, has more alternatives than C which makes it easier to discourage them)
You can use the preprocessor to catch when a macro is either 0 or defined without a value:
#define VAR
#if VAR+0 == 0
#error "VAR is either 0 or defined without a value."
#endif
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?
I have an application that uses a custom putchar(); which until now has been working fine.
I bumped up the optimization level of the application to -O2, and now my putchar isn't used.
I already use -fno-builtin, and based on some googling I added -fno-builtin-putchar to my CFLAGS, but that didn't matter.
Is there a "correct" way to get around this or do I have to go into my code and add something like
#define putchar myputchar
to be able to use -O2 and still pull in my own putchar() function?
edit--
Since my original post of this question, I stumbled on -fno-builtin-functions=putchar, as yet another gcc commandline option. Both this and the one above are accepted by gcc, but don't seem to have any noticeable effect.
edit more--
Experimenting further I see that gcc swallows -fno-builtin-yadayada also, so apparently the options parsing at the gcc front end is just passing the text after the second dash to some lower level which ignores it.
more detail:
Three files try1.c, try2.c and makefile...
try1.c:
#include <stdio.h>
int
main(int argc, char *argv[])
{
putchar('a');
printf("hello\n");
return(0);
}
try2.c:
#include <stdio.h>
int
putchar(int c)
{
printf("PUTCHAR: %c\n",c);
return(1);
}
makefile:
OPT=
try: try1.o try2.o
gcc -o try try1.o try2.o
try1.o: try1.c
gcc -o try1.o $(OPT) -c try1.c
try2.o: try2.c
gcc -o try2.o $(OPT) -c try2.c
clean:
rm -f try1.o try2.o try
Here's the output:
Notice that without optimization it uses the putchar I provided; but with -O2 it gets it from some other "magic" place...
els:make clean
rm -f try1.o try2.o try
els:make
gcc -o try1.o -c try1.c
gcc -o try2.o -c try2.c
gcc -o try try1.o try2.o
els:./try
PUTCHAR: a
hello
els:
els:
els:
els:make clean
rm -f try1.o try2.o try
els:make OPT=-O2
gcc -o try1.o -O2 -c try1.c
gcc -o try2.o -O2 -c try2.c
gcc -o try try1.o try2.o
els:./try
ahello
els:
Ideally, you should produce an MCVE (Minimal, Complete, Verifiable Example) or
SSCCE (Short, Self-Contained, Correct Example) — two names (and links) for the same basic idea.
When I attempt to reproduce the problem, I created:
#include <stdio.h>
#undef putchar
int putchar(int c)
{
fprintf(stderr, "%s: 0x%.2X\n", __func__, (unsigned char)c);
return fputc(c, stdout);
}
int main(void)
{
int c;
while ((c = getchar()) != EOF)
putchar(c);
return 0;
}
When compiled with GCC 4.9.1 on Mac OS X 10.9.4 under both -O2 and -O3, my putchar function was called:
$ gcc -g -O2 -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Werror pc.c -o pc
$ ./pc <<< "abc"
putchar: 0x61
putchar: 0x62
putchar: 0x63
putchar: 0x0A
abc
$
The only thing in the code that might be relevant to you is the #undef putchar which removes the macro override for the function.
Why try1.c doesn't call your putchar() function
#include <stdio.h>
int
main(int argc, char *argv[])
{
putchar('a');
printf("hello\n");
return(0);
}
The function putchar() may be overridden by a macro in <stdio.h>. If you wish to be sure to call a function, you must undefine the macro.
If you don't undefine the macro, that will override anything you do. Hence, it is crucial that you write the #undef putchar (the other changes are recommended, but not actually mandatory):
#include <stdio.h>
#undef putchar
int main(void)
{
putchar('a');
printf("hello\n");
return(0);
}
Note that putchar() is a reserved symbol. Although in practice you will get away with using it as a function, you have no grounds for complaint if you manage to find an implementation where it does not work. This applies to all the symbols in the standard C library. Officially, therefore, you should use something like:
#include <stdio.h>
#undef putchar
extern int put_char(int c); // Should be in a local header
#define putchar(c) put_char(c) // Should be in the same header
int main(void)
{
putchar('a');
printf("hello\n");
return(0);
}
This allows you to leave your 'using' source code unchanged (apart from including a local header — but you probably already have one to use). You just need to change the implementation to use the correct local name. (I'm not convinced that put_char() is a good choice of name, but I dislike the my_ prefix, for all it is a common convention in answers.)
ISO/IEC 9899:2011 §7.1.4 Use of library functions
Each of the following statements applies unless explicitly stated otherwise in the detailed
descriptions that follow: …
Any function
declared in a header may be additionally implemented as a function-like macro defined in
the header, so if a library function is declared explicitly when its header is included, one
of the techniques shown below can be used to ensure the declaration is not affected by
such a macro. Any macro definition of a function can be suppressed locally by enclosing
the name of the function in parentheses, because the name is then not followed by the left
parenthesis that indicates expansion of a macro function name. For the same syntactic
reason, it is permitted to take the address of a library function even if it is also defined as
a macro.185) The use of #undef to remove any macro definition will also ensure that an
actual function is referred to. Any inv ocation of a library function that is implemented as
a macro shall expand to code that evaluates each of its arguments exactly once, fully
protected by parentheses where necessary, so it is generally safe to use arbitrary
expressions as arguments.186) Likewise, those function-like macros described in the
following subclauses may be invoked in an expression anywhere a function with a
compatible return type could be called.187)
185) This means that an implementation shall provide an actual function for each library function, even if it
also provides a macro for that function.
186) Such macros might not contain the sequence points that the corresponding function calls do.
187) Because external identifiers and some macro names beginning with an underscore are reserved,
implementations may provide special semantics for such names. For example, the identifier
_BUILTIN_abs could be used to indicate generation of in-line code for the abs function. Thus, the
appropriate header could specify
#define abs(x) _BUILTIN_abs(x)
for a compiler whose code generator will accept it.
In this manner, a user desiring to guarantee that a given library function such as abs will be a genuine
function may write
#undef abs
whether the implementation’s header provides a macro implementation of abs or a built-in
implementation. The prototype for the function, which precedes and is hidden by any macro
definition, is thereby revealed also.
Judging from what you observe, in one set of headers, putchar() is not defined as a macro (it does not have to be, but it may be). And switching compilers/libraries means that now that putchar() is defined as a macro, the missing #undef putchar means that things no longer work as before.
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.