471,073 Members | 1,116 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,073 software developers and data experts.

Help with #define

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?

Nov 14 '05 #1
9 2806
On Thu, 22 Apr 2004 16:35:59 GMT, "pozz" <pN************@libero.it> wrote:
#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);

--
Robert B. Clark (email ROT13'ed)
Visit ClarkWehyr Enterprises On-Line at http://www.3clarks.com/ClarkWehyr/
Nov 14 '05 #2
Robert B. Clark wrote:
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
return 0;
}


Nov 14 '05 #3
pozz wrote:
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

Nov 14 '05 #4
- CASE - <ca**@feasture.com> wrote:
Robert B. Clark wrote:
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)
#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

return 0;
}


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

--
Z (Zo**********@daimlerchrysler.com)
"LISP is worth learning for the profound enlightenment experience
you will have when you finally get it; that experience will make you
a better programmer for the rest of your days." -- Eric S. Raymond
Nov 14 '05 #5
In <c9********************************@4ax.com> Robert B. Clark <ep****@3pynexf.pbz> writes:
On Thu, 22 Apr 2004 16:35:59 GMT, "pozz" <pN************@libero.it> wrote:
#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)


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
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #6
"- Kees van der Bent -" <kv*@mbalance.moc> ha scritto nel messaggio
news:40*********************@news.xs4all.nl...
pozz wrote:
[CUT]
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"
Nov 14 '05 #7


pozz wrote:
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

Nov 14 '05 #8
"Case -" <no@no.no> ha scritto nel messaggio
news:40**********************@dreader2.news.tiscal i.nl...


pozz wrote:
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.
Nov 14 '05 #9
pozz wrote:
#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.)

--
++acr@,ka"
Nov 14 '05 #10

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

6 posts views Thread by wukexin | last post: by
13 posts views Thread by webzila | last post: by
1 post views Thread by Paul Ferrill | last post: by
20 posts views Thread by paolo.arimado | last post: by
9 posts views Thread by Jerret Johnson | last post: by
8 posts views Thread by aaron | last post: by
11 posts views Thread by A.C. | last post: by
reply views Thread by leo001 | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.