Help with #define

P

pozz

Hi all,
I have the below #defines
#define NUMBER1 30
#define NUMBER2 50
#define SUM (NUMBER1+NUMBER2)
#define STRING1 "Byte: \x30"
#define STRING2 "Byte: \x50"

If I change NUMBER1 and NUMBER2 I must change STRING1 and STRING2
consequently.
Is there a method to #define STRING1 and STRING2 at preprocessor-time
with a number defined with a #define embedded in the string?
 
R

Robert B. Clark

#define NUMBER1 30
#define NUMBER2 50
#define SUM (NUMBER1+NUMBER2)
#define STRING1 "Byte: \x30"
#define STRING2 "Byte: \x50"

If I change NUMBER1 and NUMBER2 I must change STRING1 and STRING2
consequently.
Is there a method to #define STRING1 and STRING2 at preprocessor-time
with a number defined with a #define embedded in the string?

Sort of....

#include <stdio.h>

#define NUMBER1 30
#define NUMBER2 50
#define SUM (NUMBER1+NUMBER2)
#define STRING1 "Byte: \\x30"
#define STRING2 "Byte: \\x50"

#define NUM(x) #x
#define STRINGx(x) "Byte: \\x"##NUM(x)

int main(void)
{
printf("NUMBER1 = %d\n", NUMBER1);
printf("NUMBER2 = %d\n", NUMBER2);
printf("SUM = %d\n", SUM);

printf("STRING1 = %s\n", STRING1);
printf("STRING2 = %s\n", STRING2);

puts("Stringized macros:\n");
printf("STRING3 = %s\n", STRINGx(NUMBER1));
printf("STRING4 = %s\n", STRINGx(NUMBER2));

return 0;
}

Note that if you wanted to display the literal text "Byte: \x30", the above
will do what you want. If you intended to display "Byte: x" where x is the
character with the value 0x30, the above code will not work.

In that case, I'd abandon the macro idea and simply use the NUMBER1 macro
as an argument to printf itself:

printf("Byte: %c\n", NUMBER1);
 
C

- CASE -

Robert said:
Sort of....

#include <stdio.h>

#define NUMBER1 30
#define NUMBER2 50
#define SUM (NUMBER1+NUMBER2)
#define STRING1 "Byte: \\x30"
#define STRING2 "Byte: \\x50"

#define NUM(x) #x
#define STRINGx(x) "Byte: \\x"##NUM(x)

int main(void)
{
printf("NUMBER1 = %d\n", NUMBER1);
printf("NUMBER2 = %d\n", NUMBER2);
printf("SUM = %d\n", SUM);

printf("STRING1 = %s\n", STRING1);
printf("STRING2 = %s\n", STRING2);

puts("Stringized macros:\n");
printf("STRING3 = %s\n", STRINGx(NUMBER1));
gcc3.3: pasting ""Byte: \\x"" and "NUM" does not give a valid
preprocessing token
printf("STRING4 = %s\n", STRINGx(NUMBER2));
gcc3.3: pasting ""Byte: \\x"" and "NUM" does not give a valid
preprocessing token
 
K

- Kees van der Bent -

pozz said:
Hi all,
I have the below #defines
#define NUMBER1 30
#define NUMBER2 50
#define SUM (NUMBER1+NUMBER2)
#define STRING1 "Byte: \x30"
#define STRING2 "Byte: \x50"

If I change NUMBER1 and NUMBER2 I must change STRING1 and STRING2
consequently.
Is there a method to #define STRING1 and STRING2 at preprocessor-time
with a number defined with a #define embedded in the string?

Here's what might help you a bit further (as seen on K&R, page 231).

#define cat(a,b) a #b
#define xcat(a,b) cat(a,b)

#define NUMBER 30
#define STRING xcat("Byte: ", NUMBER)

Without success I've tried several things to get the \xNUMBER into the
STRING using CPP operators # and ##. Trying to paste an illegal 'token':
\x, to a number was what I bumped in to. Not wanting to spend too much
time, I gave up. I'm curious if it is at all possible.

BTW, are you aware of the fact that 30 != '\x30'? Maybe you could tell
more about what you want, there might be alternatives.

Cheers,

Kees
 
Z

Zoran Cutura

#define STRINGx(x) "Byte: \\x" NUM(x)
gcc3.3: pasting ""Byte: \\x"" and "NUM" does not give a valid
preprocessing token
gcc3.3: pasting ""Byte: \\x"" and "NUM" does not give a valid
preprocessing token

literal strings don't need explicit concatenation, the preprocessor
does this automagically.
 
D

Dan Pop

In said:
Sort of....

#include <stdio.h>

#define NUMBER1 30
#define NUMBER2 50
#define SUM (NUMBER1+NUMBER2)
#define STRING1 "Byte: \\x30"
#define STRING2 "Byte: \\x50"

#define NUM(x) #x
#define STRINGx(x) "Byte: \\x"##NUM(x)

Nice try, but it's undefined behaviour:

3 For both object-like and function-like macro invocations, before
^^^^^^
the replacement list is reexamined for more macro names to
replace, each instance of a ## preprocessing token in the
replacement list (not from an argument) is deleted and the
preceding preprocessing token is concatenated with the following
preprocessing token. Placemarker preprocessing tokens are
handled specially: concatenation of two placemarkers results in
a single placemarker preprocessing token, and concatenation of a
placemarker with a non-placemarker preprocessing token results
in the non-placemarker preprocessing token. If the result is
^^^^^^^^^^^^^^^^
not a valid preprocessing token, the behavior is undefined. The
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
resulting token is available for further macro replacement. The
order of evaluation of ## operators is unspecified.

So, the preprocessor concatenates "Byte: \\x" and NUM and ends up with
"Byte: \\x"NUM which is not a valid preprocessing token, hence undefined
behaviour. Some preprocessors just go on and do what you intended, which
is allowed by undefined behaviour, gcc's is more friendly and it diagnoses
the code.

Fortunately, the ## operator in your macro was a mistake in the first
place: you don't want to create a new preprocessing token out of two
preprocessing tokens. All you want to achieve is generating two adjacent
string literals, that will be spliced together in translation phase 6:

#define STRINGx(x) "Byte: \\x" NUM(x)

Dan
 
P

pozz

- Kees van der Bent - said:
pozz said:

Here's what might help you a bit further (as seen on K&R, page 231).

#define cat(a,b) a #b
#define xcat(a,b) cat(a,b)

#define NUMBER 30
#define STRING xcat("Byte: ", NUMBER)


No, it doesn't resolve my problem. In that way, I obtain
"Byte: " "30" that is "Byte: 30". I want "Byte: \x30", a
7-characters string (not counting \0 character).
BTW, are you aware of the fact that 30 != '\x30'?

Oh, yes. I know. I can define NUMBER in this way:
#define NUMBER 0x30
or
#define NUMBER 48
Maybe you could tell
more about what you want, there might be alternatives.

I want to write in an EEPROM a sequence of bytes, some ASCII
characters and some binary, using a single routine that accepts
a pointer parameters.

#define NUMBER 48
#define STRING "Hello \x30"
....
eeprom_write( STRING );
....

I can create the string at run-time, but NUMBER is costant so it's not
necessary.
But I want to use NUMBER in a mathematical expression too, so I can't
define it as
#define NUMBER "48"
 
C

Case -

pozz said:
No, it doesn't resolve my problem. In that way, I obtain
"Byte: " "30" that is "Byte: 30". I want "Byte: \x30", a
7-characters string (not counting \0 character).
I want to write in an EEPROM a sequence of bytes, some ASCII
characters and some binary, using a single routine that accepts
a pointer parameters.

#define NUMBER 48
#define STRING "Hello \x30"
...
eeprom_write( STRING );
...

I can create the string at run-time, but NUMBER is costant so it's not
necessary.
But I want to use NUMBER in a mathematical expression too, so I can't
define it as
#define NUMBER "48"

When the length of STRING is indeed always 7 then:

#define STRING "Byte: \x30"
#define NUMBER STRING[6]

This works, but because the definition of NUMBER has an
*implicit* dependency on the format of STRING, it feels
tricky/obscure.

Cheers,

Kees
 
P

pozz

Case - said:
No, it doesn't resolve my problem. In that way, I obtain
"Byte: " "30" that is "Byte: 30". I want "Byte: \x30", a
7-characters string (not counting \0 character).
I want to write in an EEPROM a sequence of bytes, some ASCII
characters and some binary, using a single routine that accepts
a pointer parameters.

#define NUMBER 48
#define STRING "Hello \x30"
...
eeprom_write( STRING );
...

I can create the string at run-time, but NUMBER is costant so it's not
necessary.
But I want to use NUMBER in a mathematical expression too, so I can't
define it as
#define NUMBER "48"

When the length of STRING is indeed always 7 then:

#define STRING "Byte: \x30"
#define NUMBER STRING[6]

This works, but because the definition of NUMBER has an
*implicit* dependency on the format of STRING, it feels
tricky/obscure.

Hmm..., I don't like that solution. NUMBER is the master symbol
and STRING is derived from that.
 
S

Sam Dennis

pozz said:
#define NUMBER1 30
#define STRING1 "Byte: \x30"

If I change NUMBER1 [...] I must change STRING1

I sort of have an answer. It doesn't work, but it's very close and
just might work on some compiler, somewhere.

#define STR( x ) #x
#define XSTR( x ) STR( x )
#define CAT( a, b ) a##b
#define BYTE( x ) XSTR( CAT( \u00, x ) )

#define NUMBER1 30
#define STRING1 "Byte: " BYTE( NUMBER1 )

This would get around the problem of \xNN not being part of a valid
identifier, except that there's a bizarre constraint with universal
character names that does not allow them to represent characters in
the range you likely want. (Almost all of ASCII is forbidden.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,043
Latest member
CannalabsCBDReview

Latest Threads

Top