By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,957 Members | 1,218 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,957 IT Pros & Developers. It's quick & easy.

stringification of __LINE__: why two passes?

P: n/a
Can someone kindly explain why stringification of the compiler
preprocessor macro __LINE__ requires two steps, instead of one? I
wanted to pass the error location of a system call to perror() and I
found that I had to use a kludgy way to stick in the line number.

Thanks,
Song

///// Code Snippet /////
#include <stdio.h>
#include <errno.h>
#include <string>

using namespace std;

#define mkstr1(X) #X
#define mkstr2(X) mkstr1(X)

#define INVALID_FD 0x10000000

main()
{
int rc;
if((rc=read(INVALID_FD, NULL, 0)) < 0)
{
string errLoc = string(__FILE__) + string(", ") +
string(mkstr2(__LINE__));
perror(errLoc.c_str());
}
}

Oct 18 '06 #1
Share this Question
Share on Google+
5 Replies


P: n/a
Generic Usenet Account wrote:
Can someone kindly explain why stringification of the compiler
preprocessor macro __LINE__ requires two steps, instead of one? I
wanted to pass the error location of a system call to perror() and I
found that I had to use a kludgy way to stick in the line number.
Macros are not recursively expanded if the expansion contains # or ##.
That's IIRC, of course.
[..]
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Oct 18 '06 #2

P: n/a
Generic Usenet Account wrote:
...
Can someone kindly explain why stringification of the compiler
preprocessor macro __LINE__ requires two steps, instead of one? I
wanted to pass the error location of a system call to perror() and I
found that I had to use a kludgy way to stick in the line number.
...
When you use #/## operators in macro definition, macro parameters adjacent to
#/## are substituted with actual argument tokens, but no further recursive macro
replacement takes place. This means that if you use another macro as the actual
argument, this macro will not be recursively replaced.

For example, in your case, if you use 'mkstr1(__LINE__)' what you'll get is
string literal "__LINE__", which normally is not the desired result. But if you
use 'mkstr2(__LINE__)' the recursive replacement of '__LINE__' with the actual
line number will take place early (at the "first pass") and by the time it gets
to # it will already be converted to a number.

--
Best regards,
Andrey Tarasevich
Oct 18 '06 #3

P: n/a
Generic Usenet Account wrote:
>
Can someone kindly explain why stringification of the compiler
preprocessor macro __LINE__ requires two steps, instead of one? I
wanted to pass the error location of a system call to perror() and I
found that I had to use a kludgy way to stick in the line number.

///// Code Snippet /////
#include <stdio.h>
#include <errno.h>
#include <string>

using namespace std;
This is a syntax error in C. You probably want comp.lang.c++.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

Oct 19 '06 #4

P: n/a
Generic Usenet Account wrote:
Can someone kindly explain why stringification of the compiler
preprocessor macro __LINE__ requires two steps, instead of one? I
wanted to pass the error location of a system call to perror() and I
found that I had to use a kludgy way to stick in the line number.

///// Code Snippet /////
#include <stdio.h>
#include <errno.h>
#include <string>

using namespace std;

#define mkstr1(X) #X
#define mkstr2(X) mkstr1(X)
....
string errLoc = string(__FILE__) + string(", ") +
string(mkstr2(__LINE__));
This is so that it is possible to convert the argument without macro
substitution. For example:

#include <assert.h>
#define IN_RANGE(x) ((x) 5 && (x) < 10))
....
assert (IN_RANGE(x));

The assert macro can use the # operator to convert the argument
IN_RANGE(x) to "IN_RANGE(x)" rather than the macro expanded version.

If you want the macro substitution first, you must invoke another macro
which has the # operator, as you did. The substitution happens as part
of the first macro expansion since it does not have a preceding # or
adjacent ## preprocessor token.

--
Thad
Oct 25 '06 #5

P: n/a
CBFalconer wrote:
Generic Usenet Account wrote:

using namespace std;

This is a syntax error in C. You probably want comp.lang.c++.
Ironically, the implicit int for main also makes this invalid in C++.

Regards,
Bart.

Oct 25 '06 #6

This discussion thread is closed

Replies have been disabled for this discussion.