Here is an overly simplified version of what I am trying to do:
#define LOGDIRECTORY C:\\logs\\
system("mkdir LOGDIRECTORY");
However the preprocessor, instead of swapping out the defined name is not. Instead the system command actually thinks LOGDIRECTORY is the name, and thus is shooting me errors when starting the program.
I know it's wrong and there must be something I can do with the " marks or other characters to specify what I want, but I can't figure it out. I don't want to hardcode the directory and file names because someone may want to change them in the future and it would be much easier to change a define than the whole function etc.
PS, I am coding this in plain C.
#define LOGDIRECTORY C:\\logs\\
#define DEF2STR(x) #x
system("mkdir " DEF2STR(LOGDIRECTORY));
#define LOGDIRECTORY_WITH_QUOTES "C:\\logs\\"
system("mkdir " LOGDIRECTORY_WITH_QUOTES);
In C, you can do simple string concatenation by writing two string literals with no operator in between. "A" "B" will be converted to "AB" at compile time. You can also use this for splitting a long string to multiple lines.
printf("a very long "
"string indeed");
To convert the define to a proper string, use the pound sign (#) in a macro or skip the whole thing and include the quotes in the define itself.
If you were compiling with GCC, you would have no choice but to wrap the define with quotes since the final trailing backslash would be interpreted as a line continuation character, and if that does not cause an error on its own, the penultimate backslash would likely raise a error. However, if you chose to just get rid of the trailing backslash, you'd still need to use two levels of stringification macros, or your syscal would be "mkdir LOGDIRECTORY". See http://gcc.gnu.org/onlinedocs/cpp/Stringification.html
So the above example would become:
#define LOGDIRECTORY C:\\logs
#define DEF2STR(x) #x
#define STR(x) DEF2STR(x)
system("mkdir " STR(LOGDIRECTORY));
Related
I'm writing C code which requires me to use multiple function calls of the same definition which differ only by single characters. Is there a way I can make a macro function which takes say a number and can insert these calls into my code for me where I call the macro given I know the numbers at compile time:
i.e.
#define call_pin_macro(X)
enable_pin#X();
do_thing_pin#X();
do_other_thing_pin#X();
.
.
void pin_function(void){
call_pin_macro(1);
call_pin_macro(2);
call_pin_macro(3);
}
Instead of:
void pin_function(void){
enable_pin1();
do_thing_pin1();
do_other_thing_pin1();
enable_pin2();
do_thing_pin2();
do_other_thing_pin2();
enable_pin3();
do_thing_pin3();
do_other_thing_pin3();
}
As a note I have looked at stringification (Hence the included #X's) in gcc however I cannot get the above code to compile which I get an error "error: '#' is not followed by a macro parameter". And it thus it seems this isn't exactly the functionality I am after. Thanks in advance.
In gcc you can do it like this:
#define call_pin_macro(X) \
enable_pin##X(); \
do_thing_pin##X(); \
do_other_thing_pin##X();
The double hash is the macro concatenation operator. You don't want to use stringify because that will put quotes around it.
The backslashes allow you to continue the macro over several lines.
#define DATA_VAR_FILENAME(PROJECT_ID) QUOTES(..\ ## PROJECT_ID ## _data_var.h)
or
#define DATA_VAR_FILENAME(PROJECT_ID) QUOTES(..\##PROJECT_ID##_data_var.h)
for the above line I got below warning
remark: unrecognized token
How to eliminate the warning ?
From the look of it, it looks that you are trying to compose a filename in the preprocessor. This is not possible like that, since the strings that form path names are not tokens for the preprocessor.
Usually there is no need for such a manipulation. String literals are simply concatenated too larger string literals in a later compilation phase. Something like
"../" "my_file.h"
should do the trick.
You also seem to have the difficulty that on your platform \ is the path separator. So you'd have to be careful to escape it in string literals, something like "..\\"
I am using regex to determine a command line argument has the .dat extension. I am trying the following regex:
#define to_find "^.*\.(dat)?"
For some reason I am getting the warning I stated in the title of this question. First, is this expression correct? I believe it is. Second, if it is correct, how can i get rid of this warning?
I am coding a c program in Xcode and the above #define is in my .h file.
Thanks!
The warning is coming from the C compiler. It is telling you that \. is not a known escape sequence in C. Since this string is going to a regex engine, you need to double-escape the slash, like this:
#define to_find "^.*\\.(dat)?"
This regex would match a string with an optional .dat extension, with dat being optional. However, the dot . is required. If you want the dot to be optional as well, put it inside the parentheses, like this: ^.*(\\.dat)?.
Note that you can avoid escaping the individual metacharacters by enclosing them in square brackets, like this:
#define to_find "^.*([.]dat)?"
You need
#define to_find "^.*\\.(dat)?"
Should do the trick as the \ needs to be escaped for C and not the benefit for regex at this stage
How to know what kind of "things" can span multiple lines in C code without needing a \ character at the end of the line?And what kind of "things" need the \?How to know that?For example, in the following code, if and printf() work fine if I split them up in multiple lines.
if
(2<5)
printf
("Hi");
But in the following code,printf() needs a \ ,else shows error:
printf("Hi \
");
Similarly,the following shows error without a \
char name[]="Alexander the \
great of Greece";
So please tell me how to know when to use the \ while spanning multiple lines in C code, and when we can do without it?I mean, like if works both with and without the \.
This is about a concept called 'tokens'. A token is source-program text that the compiler does not break down into component elements. Literals (42, "text"), variable names, keywords are tokens.
Endline escaping is important for string constants only because it breaks apart a token. In your first example line breaks don't split tokens. All whitespace symbols between tokens are ignored.
The exception is macro definitions. A macro definition is ended with line break, so you need to escape it. But macros are not C code.
If you want to break a string across lines, you can either use the \ as you have...
printf("Hello \
World");
Or, alternatively, you can terminate the string with a " and then start a new string on the next line with no punctuation...
printf("Hello "
"World");
To the best of my knowledge, the issue with lines applies in only two places... within a string and within a define..
#define MY_DEFINE(fp) \
fprintf( fp, "Hello "\
"World" );
In short, the \ character is telling the compiler this statement continues on the next line. However, C/C++ is not white-space dependent, so really the only place this would come up is on a statement that is expected to be on a single line... which would be a string or a define.
C does not depend on line feeds.
You could use line feeds anywhere you like, as well as just not using them at all.
This implies seeing string literals as one token.
But, as in real life: Too much or to few, both does make life difficult. Happyness is matter of balance ... :-)
Please note that lines starting with a # are not C code, but pre-processor instructions.
I have this problem in a header macro expansion under Microsoft C Compiler Preprocessor:
custom.h
.
.
# define _OTHER_INCLUDE_DIR C:\3rdparty\usr\include
# define _3RD_PARTY_HEADERS(headername) <_OTHER_INCLUDE_DIR\headername>
.
.
With a header test:
headertest.h
.
.
#include _3RD_PARTY_HEADERS(stdint.h)
.
Microsoft C preprocessor expand second line like(custom.h):
#include <C:\3rdparty\usr\include\headername>
If I set :
# define _3RD_PARTY_HEADERS(headername) <_OTHER_INCLUDE_DIR\ headername>
The result is:
#include <C:\3rdparty\usr\include\ stdint.h>
How I can fix that?
It looks like you want to juxtapose your directory and your header name. You use ##, like this:
# define _3RD_PARTY_HEADERS(headername) <_OTHER_INCLUDE_DIR\\##headername>
Is there no way to have the \ character sequences to be represented differently? The problem is that this is an escape character for C and C++. C99 explicitly states
If the characters ', \, ", //, or /*
occur in the sequence between the <
and > delimiters, the behavior is
undefined.
(There is a similar phrase for "..." includes.)
and I imagine that for C++ there must be something similar. So maybe you just could use / and the compiler would replace them internally to refer to the correct file on your system.
You know, most compilers have a command-line argument to add to the include path... -I or /I most likely for the Microsoft one. One doesn't usually do what you're doing here, never mind whether or not you can make it work.