Can you store the pointer address in a variable and print that out?
If you want to print the value of a pointer without using the format %p specifier, you can cast the pointer to an integer that has the same size and then print the integer value.
To print the address of something on Arduino do something like
Serial.println (&x, HEX);
Actually, you can't do this without a cast. (Did you try it?)
The Arduino print functions do not have a version that is defined to print a pointer to int.
The sketch is compiled as part of a C++ program, and C++ enforces a certain amount of data type integrity. The C++ compiler won't let you assign a pointer value to some non-pointer data type, so you have to use a cast of some kind. For me, the simplest is just an old C-style cast.
The only thing is that you have to make sure the size of the integer data type is the same size as the pointer, so the method is not portable.
In other words, when you are casting a pointer to another data type it is up to you to make sure they are commensurate.
Now, with avr-gcc (Arduino's compiler) the size of an int is two bytes and the size of a pointer is two bytes.
You can verify this by running something like the following. Note that sprintf
does support printing with %p
format specifier, so I use that to compare output with various ways of using casts.
// Printing pointer values
char x = "Hi";
sprintf(buffer, "with %%p: x = %p\n", x);
sprintf(buffer, "with %%p: &x = %p\n", &x);
y = &x; // Same as writing y = x;
z = (unsigned int)y;
Serial.print("sizeof(unsigned int) = ");Serial.print(sizeof(unsigned int));
Serial.print(", sizeof(char *) = "); Serial.println(sizeof(char *));
Serial.print("(unsigned int)y = 0x");Serial.println(uint16_t(y),HEX);
Serial.print("(unsigned int)x = 0x");Serial.println((unsigned int)x,HEX);
Serial.print("(unsigned int)&x = 0x");Serial.println((unsigned int)&x,HEX);
Serial.print(" z = 0x");Serial.println(z,HEX);
Serial.print("&z = 0x");Serial.println((unsigned int)&z, HEX);
with %p: x = 0x8d5
with %p: &x = 0x8d5
sizeof(unsigned int) = 2, sizeof(char *) = 2
(unsigned int)y = 0x8D5
(unsigned int)x = 0x8D5
(unsigned int)&x = 0x8D5
z = 0x8D5
&z = 0x8D3
Bottom line: Whatever method you use to put integer values to your uart can be used to put pointer values. At the receiving end, the program reading the integer value can cast it to a pointer type and use it for whatever it needs to do.
Note that sprintf with "%p" always prints hex and the version in avr-libc (like all GNU compiler libraries that I have used) always puts "0x" in front of it. By using a cast to unsigned int instead of sprintf, you can print with whatever base you want. As long as the sender and receiver agree on the exact format, All is Good.