Use a #define in printf? - c++

I was wanting to use a constant of some kind for the application ID (so I can use it in printf).
I had this:
#define _APPID_ "Hello World!"
And then the simple printf, calling it into %s (string). It put this out:
simple.cpp:32: error: cannot convert ‘_IO_FILE*’ to ‘const char*’ for argument ‘1’ to ‘int printf(const char*, ...)’
What would I use to define the application ID to use in printf? I tried:
static const char _APPID_[] = "Hello World"`
but it didn't work, same error I think.

I'm not sure I understand exactly what you tried... but this works:
#include <stdio.h>
#define _APPID_ "Hello world"
int main()
{
printf("The app id is " _APPID_ "\n");
/* Output: The app id is Hello world */
return 0;
}
When presented with two constant strings back to back (i.e. "hello " "world"), the compiler treats them as a single concatenated constant string ("hello world").
That means that in the case of trying to printf a compile-time constant string, you don't need to use printf("%s", _APPID_) (although that should still work).

According to the error message, the problem is most likely not caused by the string constant, but by incorrect parameters given to printf().
If you want to print to a file, you should use fprintf(), not printf(). If you want to print to the screen, use printf(), but don't give a file handle as its first parameter.

In source.h
#ifndef _SOURCE_H
#define SOURCE_H
#ifdef APP_ID
#define WHOAMI printf("%s\n", APP_ID);
#endif
#endif
In your program:
#define APP_ID __FILE__
#include "source.h"
int main()
{
WHOAMI
return 0;
}
the reason for this is to have a stadnard include file - source.h. __FILE__ inside a header file returns the name of the header file, so the APP_ID definition is constrained to live in the C file.
If you don't define APP_ID the code won't compile.

_APPID_ is a name that's reserved for the implementation. It matches the pattern ^_[A-Z].*
Rename it to e.g. APP_ID.

Related

Append the string provided by __FUNCTION__ macro

I have defined a macro as following:
#define ADD_TIME_ENTRY(_name_) m_pTimeMeasurement->addTimeEntry(_name_);
Now, I want to pass the function name through ADD_TIME_ENTRY() in whichsoever function I put ADD_TIME_ENTRY()
ADD_TIME_ENTRY(__FUNCTION__) works fine for me but now, I want to add "_start" or "_stop" at the end of the function name. I mean, I need something like "imageFunction()_start" but I am not able to do it.
I want to do it in a single line i.e.
imageFunction()
{
ADD_TIME_ENTRY(__FUNCTION__ ....something here...);
}
You can add an additional macro #define STRINGIZE(str) #str and use it like this: ADD_TIME_ENTRY(__FUNCTION__ STRINGIZE(start))
Seems like __FUNCTION__ might be not a macro so it is not particularly easy to combine it with anything in such a case. In MSVC2013 it is a macro so it is easy combinable. For other compilers I'd try the following:
#define GIVE_ME_NAME(tag) std::string(__FUNCTION__) + STRINGIZE(tag)
Not particularly efficient but working way.
Example:
#include <iostream>
#include <string>
using namespace std;
#define STRINGIZE(str) #str
#define GIVE_ME_NAME(tag) std::string(__FUNCTION__) + STRINGIZE(tag)
int main()
{
std::cout << GIVE_ME_NAME(start);
};
As __FUNCTION__ is of type static "const char __FUNCTION__[]" , when you call m_pTimeMeasurement->addTimeEntry(_name_),addTimeEntry function parameter will be "const char __FUNCTION__[]".
So you can concatenate two char variables and pass it
ADD_TIME_ENTRY(strcat(const_cast< char *>(__FUNCTION__),"_start"));
ADD_TIME_ENTRY(strcat(const_cast<char *>(__FUNCTION__),"_stop"));

cross platform printing 64-bit intergers through a customized printf function

There is a debug class that is used to print out debug statements based on a level. The higher the level, the more detailed messages you would get. The problem occurs when I am trying to do print out a uint64_t. On different platforms using printf style it could be either %li or %lli. I want it to become portable. However, based on this, I could include a PRId64 and it would adjust accordingly. The problem is because my messages are customized, it takes in a const char *. I am unable to do with with a message such as "Calling based on pts %"PRId64, mv.pts because it is expecting a char * where there isn't one. What are other approaches in solving this?
Inside the main code
#include "debug.h"
#include <inttypes.h>
#define P_DBG(level, format, ...) DBGPRINT(level, ("%-5d%s::%s() - " format "\n", __LINE__, str().c_str (), __FUNCTION__, __VA_ARGS__))
#define P_ALL(format, ...) P_DBG(P_ALWAYS, format, __VA_ARGS__)
class Something
{
Something::Print(uint64_t a) {
P_ALL("Calling based on %"PRId64 "\n", a)
}
Inside debug.h
class vdebugPrint {
class vdebugPrint(int ID, int level) : v_id(ID), v_level(level) {}
int Print(const char* formatString, ...) __attribute__((__format(printf,2,3)));
}
...
#define VPRINT3(level, msg) VdebugPrint(ID, level).Print msg
#define PRINT(level, msg) VPRINT##level(level,msg)
#define DBGPRINT(level, msg) PRINT(level,msg)
...
Inside debug.cpp
...
VdebugPrint::Print(const char* format, ...)
{
va_list argumentList;
va_start(argumentList, formatString);
vprintf(formatString, argumentList);
va_end(argumentList);
}
The exact error message is
error: expected ‘)’ before ‘PRId64’
AV_TRACE("Calling based on %"PRId64"\n", mv.pts);
^
/.../debug.h:140:94: note: in definition of macro ‘VPRINT3’
#define VPRINT3(level, msg) VdebugPrint(ID, level).DebugPrint msg
/.../debug.h:146:45: note: in expansion of macro ‘DBGPRINT’
#define DBGPRINT(level, msg) PRINT(level, msg)
^
/.../file.h:54:41: note: in expansion of macro ‘DBGPRINT’
#define P_PBD(level, format, args...) DBGPRINT(level, ("%-5d%s::%s() - " format "\n", __LINE__, str().c_str(), __FUNCTION__, ##args))
EDIT:
I've attempted Olaf suggestion to no avail. Here is what I've done. Everything else is the same except for the main code.
...
class Something
{
Something::Print(uint64_t a) {
const char* message = "Calling based on %";
size_t mlen = strlen(message);
char buf[mlen + strlen(PRId64) + 1];
strcpy(buf, message);
strcpy(buf + mlen, PRId64);
P_ALL(buf, a);
}
}
The error that I get is
error: ‘PRId64’ was not declared in this scope
char buf[mlen + strlen(PRId64) + 1];
^
EDIT2: So I fixed the problem with it not finding PRId64. I had to define __STDC_FORMAT_MACROS from here before include inttypes. This now solves the problem and it compiles!
The macros defined in inttypes.h are string literals with the proper printf type specifier. So you have to append this to the format string. Normal usage would be to use string literal concatenation.
If your format string is variable, you have to append the specifier to the string:
char buf[strlen[format] + strlen[PRId64] + 1];
strcpy(buff, format);
strcat(buff, PRId64);
Note this could be optimized using strcpy for both:
size_t flen = strlen(format);
char buf[flen + strlen[PRId64] + 1];
strcpy(buff, format);
strcpy(buff + flen, PRId64);
Caution: The format string has to be NUL-terminated!
Update:
The original answer was for C as that was one of the language-tags and the code looked more like C than C++. However, according to comments, you can use this also for C++11 (check your compiler's support), if you #define __STDC_FORMAT_MACROS before #include <inttypes.h>. (Note the include might appear in other headers, so you should define the macro as early as possibly in your file.)
You need spaces between the adjacent string literals and the macros for the expansion and concatenation to work. For example:
// Note the space on either side of PRId64
AV_TRACE("Calling based on %" PRId64 "\n", mv.pts);
(I don't know if this is required according to the standard, but it is required to make it work for some preprocessors I've used.)

Is it possible to read a file at compile time?

I am wondering if it is possible in C++11/14 to actually read files at compile time. For example the following code will only compile if it can successfully read the file.
constexpr std::string shader_source = load("~/foo.glsl");
Do you think this could be possible?
I know that I could do this with some custom tool when building my application.
Building on teivaz's idea, I wonder if the usual "stringize after expansion" trick will work:
#define STRINGIZE(...) #__VA_ARGS__
#define EXPAND_AND_STRINGIZE(...) STRINGIZE(__VA_ARGS__)
constexpr std::string shader_source = EXPAND_AND_STRINGIZE(
#include "~/.foo.glsl"
);
Still, I would go for a conventional extern const char[] declaration resolved to the content by the linker. The article "Embedding a File in an Executable, aka Hello World, Version 5967" has an example:
# objcopy --input binary \
--output elf32-i386 \
--binary-architecture i386 data.txt data.o
Naturally you should change the --output and --binary-architecture commands to match your platform. The filename from the object file ends up in the symbol name, so you can use it like so:
#include <stdio.h>
/* here "data" comes from the filename data.o */
extern "C" char _binary_data_txt_start;
extern "C" char _binary_data_txt_end;
main()
{
char* p = &_binary_data_txt_start;
while ( p != &_binary_data_txt_end ) putchar(*p++);
}
#define STR(x) #x
const char* a =
{
#include "foo.glsl"
};
and foo.glsl should enclose its content in
STR(
...
)
upd. This will properly handle commas
#define STRINGIFY(...) #__VA_ARGS__
#define STR(...) STRINGIFY(__VA_ARGS__)
I have done something like this. See if this will give you what you want.
Add a command line option to the program that checks for the existence and validity of the input file.
That option should exit the program with an error code if the file does not exist, or is not valid.
In your make file, add a call to the program (using that command line option), as the final build step.
Now when you build the program, you will get an error if the proper files are not available or not valid.
This is my C solution, but for C++ is the same. Stringify #define does not work with #include in my case with modern compilers, so you can use raw string literals inside your file to embed the content inside a string at compile time.
test.c:
#include <stdio.h>
const char *text = {
#include "test.dat"
};
int main() {
printf("%s\n", text);
}
test.dat:
R"(This is a line.
This is another line...)"

what is the result about the recursive Macro spread?

#include <iostream>
#define help(a) #a
#define xhelp(a) help(a)
#define glue(a,b) a##b
#define xglue(a,b) glue(a,b)
#define HIGHLOW "hello"
#define LOWLOW ",world"
int main()
{
std::cout<<xhelp(xglue(HIGH,LOW))<<std::endl;
return 0;
}
here is my test code. I want to know the spread of the MACOR xglue(HIGH,LOW).
For me, i think the result is "hello"
but i learn from one website, the result is "hello, world".
I am really confused with it.
the result of my code is aslo "hello".
Is there anyone could help me with it?
I think the xgule(HIGH,LOW)=glue(HIGH,LOW)=HIGHLOW="hello"
THe website show that xglue(HIGH,LOW)=glue(HIGH,LOW",world")="hello, world"
First of all, there is no recursive macro.
Most work in the example is performed by the two preprocessor operators # and ##.
# is a unary operator that turns its argument into a string literal.
## is a binary operator that pastes two tokens together to form one single token.
The easiest way to check what a given preprocessor code expands to is actually to run the preprocessor. The g++ compiler has a -E option to do exactly that.
# Assuming your file is saved as code.cpp
$ g++ -E code.cpp
... lots of output ...
int main()
{
std::cout<<"\"hello\""<<std::endl;
return 0;
}

CPP: avoiding macro expansion of a macro function parameter

what I'd like to do (for logging purposes) is something like this:
This code has been written to show my problem, actual code is complex and yes, I have good reasons to use macros even on C++ =)
# define LIB_SOME 1
# define LIB_OTHER 2
# define WHERE "at file #a, line #l, function #f: "
// (look for syntax hightlighting error at SO xd)
# define LOG_ERROR_SIMPLE(ptr, lib, str) ptr->log ("ERROR " str \
" at library " #lib);
# define LOG_ERROR(ptr, lib, str) LOG_ERROR_SIMPLE(ptr, lib, WHERE str)
LOG_ERROR_SIMPLE (this, LIB_SOME, "doing something")
LOG_ERROR (this, LIB_OTHER, "doing something else")
LOG_ERROR_SIMPLE() writes the stringification of the lib parameter (a macro name surrounded by " ")
but then LOG_ERROR writes the stringification of the macro already expanded ("2"). this is expected, since lib got its expansion before expanding and calling LOG_ERROR_SIMPLE. but this is not what I need.
Basically my question is this: how to avoid macro expansion of a macro function parameter when calling another macro function?
There is a trick I use that avoids macro expansion:
LOG_ERROR(ptr, lib, str, x) LOG_ERROR_SIMPLE(ptr, x##lib, WHERE str)
LOG_ERROR(this, LIB_OTHER, "some error",)
(pasting x and lib produces LIB_OTHER and this value is used to call LOG_ERROR_SIMPLE, its not macro expanded before that call)
There is some way to obtain this same behaviour without using a trick?
I'm doing:
#include <cstdio>
#define FOO 1
#define BAR 2
#define LOG_SIMPLE(ptr, lib, str) printf("%s\n", #lib);
#define LOG(ptr, lib, str) LOG_SIMPLE(ptr, ##lib, str)
int main()
{
LOG_SIMPLE(0, FOO, "some error");
LOG(0, BAR, "some other error");
}
which prints out:
FOO
BAR
Works with MSVC2005 but not with gcc/g++.
EDIT: to make it work with gcc/g++ you can abuse variadic macros:
#include <stdio.h>
#define FOO 1
#define BAR 2
#define LOG_SIMPLE(ptr, str, lib) printf("%s\n", #lib);
#define LOG(ptr, str, lib, ...) LOG_SIMPLE(ptr, str, lib##__VA_ARGS__)
int main()
{
LOG_SIMPLE(0, "some error", FOO);
LOG(0, "some other error", BAR);
LOG(0, "some other error", FOO, BAR);
}
However, it's your discipline not to use the macro with too many parameters. MSVC2005 prints out
FOO
BAR
FOO2
while gcc prints out
FOO
BAR
FOOBAR
If you don't need the expanded lib aliases (i.e. '1' & '2') in your cpp macros, you could also use an enum instead of defined values.
I don't think you can. What you could do, though, is add a layer of macro for it to unpeel in its place:
#define WRAP(x) x
#define LOG_ERROR(ptr, lib, str) LOG_ERROR_SIMPLE(ptr, lib, WHERE WRAP(str))
You almost had it. Use
#define LOG_ERROR(ptr, lib, str) LOG_ERROR_SIMPLE(ptr, ##lib, WHERE str)
On gcc
LOG_ERROR(this, LIB_OTHER, "some error")
yields
this->log ("ERROR " "at file #a, line #l, function #f: " "some error" " at library " "LIB_OTHER");
I would also remove the trailing ';' from your macro so that your code would look like:
LOG_ERROR(this, LIB_OTHER, "some error");