Go Down

Topic: Need to print pointer address to uart without using printf or sprintf (Read 4 times) previous topic - next topic

renasis

Hello,

I would like to print a pointer address to the uart without using printf or sprintf with %p parameter. Is this possible? Including these functions takes up too much space in my bootloader. I have found Can you store the pointer address in a variable and print that out? The only function that I have to print to uart is putchar(char ch).

Thanks,

-ren

Graynomad

What system are you using, I don't think those functions are implemented on Arduino.

To print the address  of something on Arduino do something like

int x;

Serial.println (&x, HEX);

______
Rob
Rob Gray aka the GRAYnomad www.robgray.com

davekw7x

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

int x;
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.

Code: [Select]

// Printing pointer values
//   davekw7x

void setup()
{
   Serial.begin(9600);
}

void loop()
{
   char buffer[30];
   char x[3] = "Hi";
   char *y;
   int z;
   sprintf(buffer, "with %%p:  x    = %p\n", x);
   Serial.print(buffer);
   sprintf(buffer, "with %%p: &x[0] = %p\n", &x[0]);
   Serial.print(buffer);

   y = &x[0]; // 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[0] = 0x");Serial.println((unsigned int)&x[0],HEX);
   Serial.print(" z = 0x");Serial.println(z,HEX);
   Serial.print("&z = 0x");Serial.println((unsigned int)&z, HEX);

   Serial.println();
   delay(10000);
}



Output:

with %p:  x    = 0x8d5
with %p: &x[0] = 0x8d5
sizeof(unsigned int) = 2, sizeof(char *) = 2
(unsigned int)y     = 0x8D5
(unsigned int)x     = 0x8D5
(unsigned int)&x[0] = 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.

Regards,

Dave
Footnote:
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.

PaulS

Being able to do something does not mean that it is smart to do it. Typically, pointers are useful only on the system they were defined on. So, what value does the pointer you are trying to send have on another system? In other words, why are you trying to write a pointer's address to the serial port?

tim7

Using only putchar():

Code: [Select]

  int ptr = (int) &value;                 // store 16-bit address, and then pretend that memory is a character array
  putchar( *(1+ (unsigned char*) &ptr) ); // MSB
  putchar( *( (unsigned char*) &ptr) );   // LSB


Go Up