Stringify complex expression

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Greetings

I have a problem with stringification of a pre-processor macro.

 


#define FAST_SIN_PHASE_RESOLUTION	            1024
#define PZT_TICK_FREQ_TO_FASTSIN_RES_SHIFTS		2
#define PZT_TICK_PERIOD		                    (FAST_SIN_PHASE_RESOLUTION << PZT_TICK_FREQ_TO_FASTSIN_RES_SHIFTS)
#define PZT_DUAL_MAX_FREQ	                    (PZT_TICK_PERIOD/2)

#define xstr(s) str(s)
#define str(s) #s

// ...

service_init_decimal_input(pState, service_fsm_get_frequency, PSTR("Enter frequency (0 to " xstr(PZT_DUAL_MAX_FREQ) " Hz): "), 0, PZT_DUAL_MAX_FREQ);

When compiled I get this assembly output:


__c.1863:
	.string	"Enter frequency (0 to ((1024 << 2)/2) Hz): "

which is obviously not quite what I want. The line should say "... (0 to 2048 Hz):".

 

I tried defining more levels of xstr macros:


#define xstr3(s) xstr2(s)
#define xstr2(s) xstr(s)
#define xstr(s) str(s)
#define str(s) #s

but neither will give me the fully evaluated expression in the string. How can I achieve this?

 

ATMEL Studio 7.0.1006

GCC: (AVR_8_bit_GNU_Toolchain_3.5.3_1700) 4.9.2

 

/Jakob Selbing

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jaksel wrote:
How can I achieve this?
You can't achieve it that way. The preprocessor doesn't do the math, it only does text replacement. The math is done later by the compiler, but of course not within a string.

You either need to do the conversion into a string at runtime, or you use a magic number in the source code. I would favour the former.

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Use Python or similar to generate the C and #include

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the input. It's frustrating that the preprocessor cannot do that, but at the same time it can obviously evaluate arithmetic expressions in #if statement conditions.

 

Actually, this type of problems arises for me quite often. I use macros a lot, and also try to define each fundamental value separately. Sometimes I use workarounds that involve magic numbers but always with an #if statement self-check.

 

In this case I think one for me acceptable solution is:

#define PZT_DUAL_MAX_FREQ_VAL	2048						// Redundant definition; must be self-checked

#if (PZT_DUAL_MAX_FREQ != PZT_DUAL_MAX_FREQ_VAL)
	#error PZT_DUAL_MAX_FREQ and PZT_DUAL_MAX_FREQ_VAL must be equal!
#endif

//...

service_init_decimal_input(pState, service_fsm_get_frequency, PSTR("Enter frequency (0 to " xstr(PZT_DUAL_MAX_FREQ_VAL) " Hz): "), 0, PZT_DUAL_MAX_FREQ);

 

/Jakob Selbing

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I suspect that your macros only ever evaluate as a few different texts,
Just use the preprocessor maths in conditionals to define the appropriate string.
.
Yes, it looks long winded. But you hide it in a header file.
.
David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's frustrating that the preprocessor cannot do that, but at the same time it can obviously evaluate arithmetic expressions in #if statement conditions.

Expressions in preprocessor conditionals are the >>only<< cases where the preprocessor will perform arithmetic.  That is part of the standard.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

An important aspect of doing it right is knowing that you have done it right.

As noted, he preprocessor will do arithmetic in a conditional:

#define number 666
... xstr(number) ...
#if number != expression
    #error
#endif

If you have it, static_assert is better: static_assert(number==expression);

"SCSI is NOT magic. There are *fundamental technical
reasons* why it is necessary to sacrifice a young
goat to your SCSI chain now and then." -- John Woods