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

How to pass COMMA as an operator into macro. (Not the FAQ).

P: n/a
Hi all,

This is not a question about how to #define COMMA ,
Please keep reading.

Recently in binutils, we introduced a macro like this:

#define STRING_COMMA_LEN(STR) \
(STR), ((STR) ? sizeof (STR) - 1 : 0)

So in cases where we have a struct like this:

struct astruct
{
const char* str;
size_t len;
};

We can replace the manually inserted length:

struct astruct astruct_inst[] =
{ {"a string", 8} };

With:

struct astruct astruct_inst[] =
{ { STRING_COMMA_LEN("a string") } };

All good.

On with the question:

If you try to compile the code below, and strncmp happens to be a
macro,
the compiler will complain with an error, because the comma inserted
by STRING_COMMA_LEN will not be considered an operator by the time
strncmp is evaluated.

const char *a;
strncmp (a, STRING_COMMA_LEN("a string"));

Is there *any* way the STRING_COMMA_LEN could be changed
so this compiles, without touching the strncmp definition?

Or more generally, is there any way a macro can generate a comma
that will be considered an operator by the next macro?

Cheers,
Pedro Alves

Sep 18 '06 #1
Share this Question
Share on Google+
6 Replies


P: n/a
pedroalves wrote:
Recently in binutils, we introduced a macro like this:

#define STRING_COMMA_LEN(STR) \
(STR), ((STR) ? sizeof (STR) - 1 : 0)
Why use the conditional operator, you will get 0 for "" anyway?
So in cases where we have a struct like this:

struct astruct
{
const char* str;
size_t len;
};

We can replace the manually inserted length:

struct astruct astruct_inst[] =
{ {"a string", 8} };

With:

struct astruct astruct_inst[] =
{ { STRING_COMMA_LEN("a string") } };

All good.

On with the question:

If you try to compile the code below, and strncmp happens to be a
macro, the compiler will complain with an error, because the comma
inserted by STRING_COMMA_LEN will not be considered an operator
by the time strncmp is evaluated.

const char *a;
strncmp (a, STRING_COMMA_LEN("a string"));

Is there *any* way the STRING_COMMA_LEN could be changed
so this compiles, without touching the strncmp definition?
One way is to force a function call...

(strncmp)(a, STRING_COMMA_LEN("a string"));

But I think stylistically, it's better to scrap your macro and make the
code more obvious...

#define LITLEN(x) ((sizeof x) - 1)

static char a_string[] = "a string"; /* or #define, but somewhere
more
accessible that buried deep in the source code */

strncmp(a, a_string, LITLEN(a_string));
Or more generally, is there any way a macro can generate a comma
that will be considered an operator by the next macro?
Not in the way you want, AFAIK.

You can use an intermediate macro...

#define STRNCMPLIT(a,b) strncmp(a, b)

STRNCMPLIT(a, STRING_COMMA_LEN("a string"));

Or...

#define STRNCMPLIT2(a,b) \
APPLY(foo, a, STRING_COMMA_LEN(b))

#define APPLY(m, a, b) m(a, b)

STRNCMPLIT2(a, "a_string");

But the fact is... strncmp takes three arguments. All you're doing is
obfuscating
that. The situation is no different for the general case.

--
Peter

Sep 18 '06 #2

P: n/a
Peter Nilsson wrote:
pedroalves wrote:
Recently in binutils, we introduced a macro like this:

#define STRING_COMMA_LEN(STR) \
(STR), ((STR) ? sizeof (STR) - 1 : 0)

Why use the conditional operator, you will get 0 for "" anyway?
So that you will get 0 for NULL.

Sep 18 '06 #3

P: n/a
Ark
pedroalves wrote:
Hi all,

This is not a question about how to #define COMMA ,
Please keep reading.

Recently in binutils, we introduced a macro like this:

#define STRING_COMMA_LEN(STR) \
(STR), ((STR) ? sizeof (STR) - 1 : 0)

So in cases where we have a struct like this:

struct astruct
{
const char* str;
size_t len;
};

We can replace the manually inserted length:

struct astruct astruct_inst[] =
{ {"a string", 8} };

With:

struct astruct astruct_inst[] =
{ { STRING_COMMA_LEN("a string") } };

All good.

On with the question:

If you try to compile the code below, and strncmp happens to be a
macro,
the compiler will complain with an error, because the comma inserted
by STRING_COMMA_LEN will not be considered an operator by the time
strncmp is evaluated.

const char *a;
strncmp (a, STRING_COMMA_LEN("a string"));

Is there *any* way the STRING_COMMA_LEN could be changed
so this compiles, without touching the strncmp definition?

Or more generally, is there any way a macro can generate a comma
that will be considered an operator by the next macro?

Cheers,
Pedro Alves
If I remember correctly the macro expansion rules in this late hour, you
need to wrap the /target/ macro to achieve the result you want:
#define STRNCMP(str, combo) strncmp(str, combo)
- Ark
Sep 18 '06 #4

P: n/a

Peter Nilsson wrote:
pedroalves wrote:
Is there *any* way the STRING_COMMA_LEN could be changed
so this compiles, without touching the strncmp definition?

One way is to force a function call...

(strncmp)(a, STRING_COMMA_LEN("a string"));
Humm, I can't get this to compile.
#define my_strncmp(A, B, C)

#define STRING_COMMA_LEN(STR) \
(STR), ((STR) ? sizeof (STR) - 1 : 0)

int main()
{
const char* a;
(my_strncmp)(a, STRING_COMMA_LEN("a string"));
return 0;
}

main.c:9: error: `my_strncmp' undeclared (first use in this function)

I must be missing something.
>
But the fact is... strncmp takes three arguments. All you're doing is
obfuscating
that. The situation is no different for the general case.
Yes, I agree. This was just an example.
I wanted this to build new macros on top of existing ones.
Thanks all, this has been very enlightning.

Sep 18 '06 #5

P: n/a
pedroalves wrote:
Peter Nilsson wrote:
pedroalves wrote:
Is there *any* way the STRING_COMMA_LEN could be changed
so this compiles, without touching the strncmp definition?
One way is to force a function call...

(strncmp)(a, STRING_COMMA_LEN("a string"));

Humm, I can't get this to compile.
#define my_strncmp(A, B, C)

#define STRING_COMMA_LEN(STR) \
(STR), ((STR) ? sizeof (STR) - 1 : 0)

int main()
{
const char* a;
(my_strncmp)(a, STRING_COMMA_LEN("a string"));
return 0;
}

main.c:9: error: `my_strncmp' undeclared (first use in this function)

I must be missing something.
That's because you haven't declared a (non-macro) function called
my_strncmp.

If you're now telling me that your 'strncmp' example wasn't strncmp but
was
infact a different macro foo (say) that calls a function not called
foo, then
that changes things.

--
Peter

Sep 18 '06 #6

P: n/a
Harald van Dijk wrote:
Peter Nilsson wrote:
pedroalves wrote:
Recently in binutils, we introduced a macro like this:
>
#define STRING_COMMA_LEN(STR) \
(STR), ((STR) ? sizeof (STR) - 1 : 0)
Why use the conditional operator, you will get 0 for "" anyway?

So that you will get 0 for NULL.
I figured, although that use is incompatible with the strncmp example
given
later in the OP's post.

--
Peter

Sep 18 '06 #7

This discussion thread is closed

Replies have been disabled for this discussion.