1

I'm writing code in the Arduino (1.6.5) environment. In my code, I want to be able to define a string value, then use it and also Serial.println() it to the serial console.

For example:

#define THEVAL 12345      // Define the value
...
v = v + THEVAL;     // Use the value in code.
...
Serial.println("The value is: #THEVAL");      // Show the value to user (for debugging)

However, the compiler doesn't replace constants inside quoted strings. I also tried this (C++ stringification) which indicates that you place the constant outside the quoted string

#define THEVAL 12345
...
Serial.println("This is the value: " #THEVAL);

but that yields a "Stray # character" error in the compiler.

I'd appreciate any insight! Thanks!

EDIT: ODD BEHAVIOR

On testing I discovered the following: (Note: the IP address uses commas to separate the octets because each octet is passed as a separate parameter to the EthernetServer.begin in a byte array (byte ip[] = { a, b, c, d })

#define IP_ADDRESS 192,168,1,1
#define IP_ADDRESS_STRING(a,b,c,d) xstr(a)"."xstr(b)"."xstr(c)"."xstr(d)
#define xstr(a) str(a)
#define str(a) #a

If I do the following, I get the error "IP_ADDRESS_STRING requires 4 arguments, but only one given"

debug("IP Address is: " IP_ADDRESS_STRING(IP_ADDRESS));

but if I do the following, I get the error "macro 'str' passed 4 arguments, but just takes 1"

debug("IP ADDRESS: " xstr(IP_ADDRESS));

But if I do this, it works:

String ipAddressString(int a, int b, int c, int d)
{
    return String(a) + "." + String(b) + "." + String(c) + "." + String(d);
}

debug("IP Address is: " + ipAddressString(IP_ADDRESS));

I'm confused - why does one macro consider IP_ADDRESS to be a single argument, and the other macro sees it as 4 arguments, while the function works correctly: it sees 4 arguments?

Ryan Griggs
  • 2,457
  • 2
  • 35
  • 58

4 Answers4

2
#define XSTR(s) STR(s)
#define STR(s) #s
....
#define THEVAL 12345
....
Serial.println("The value of " STR(THEVAL) " is " XSTR(THEVAL));

This would output:

The value of THEVAL is 12345
Ian Abbott
  • 15,083
  • 19
  • 33
1
#define XSTR(s) STR(s)
#define STR(s) #s
....
#define THEVAL 12345
....
Serial.println("The value of " STR(THEVAL) " is " XSTR(THEVAL));

But if THEVAL is set to 123,456 this fails.

With a slight modification it also works:

#define STR(...) #__VA_ARGS__
Armali
  • 18,255
  • 14
  • 57
  • 171
0

suggest

Serial.print("This is the value: ");
Serial.println( THEVAL );

or

int x = THEVAL;
Serial.print("This is the value: ");
Serial.println( x );
user3629249
  • 16,402
  • 1
  • 16
  • 17
0

I'm confused - why does one macro consider IP_ADDRESS to be a single argument, and the other macro sees it as 4 arguments, while the function works correctly: it sees 4 arguments?

In the invocation IP_ADDRESS_STRING(IP_ADDRESS), there is obviously only the one argument IP_ADDRESS, and this is true irrespective of how IP_ADDRESS is defined, because argument substitution takes place only after the arguments for the invocation of a function-like macro have been identified (ISO/IEC 9899:201x).

In the invocation xstr(IP_ADDRESS) with the definition #define xstr(a) str(a), according to the above the parameter a is then replaced by the one argument IP_ADDRESS after that macro has been expanded (macro replaced), yielding str(192,168,1,1), so str is passed 4 arguments.

In contrast to the first case, in a function call ipAddressString(IP_ADDRESS) the substitution of IP_ADDRESS takes place not after, but before the arguments for the function call are identified.

You can use the macro by the same two-stage technique that's utilized with xstr()/str():

#define IP_ADDRESS 192,168,1,1
#define XIP_ADDRESS_STRING(abcd) IP_ADDRESS_STRING(abcd)
#define IP_ADDRESS_STRING(a,b,c,d) xstr(a)"."xstr(b)"."xstr(c)"."xstr(d)
#define xstr(a) str(a)
#define str(a) #a
debug("IP Address is: " XIP_ADDRESS_STRING(IP_ADDRESS));
Armali
  • 18,255
  • 14
  • 57
  • 171