Can Serial.print display a memory address

I'm playing with pointers and would like to print the value of the pointer (the actual address stored in the pointer variable) and not the value at that address. I get a cascade of compiler errors which amount to incorrect variable type passed to Serial.print()

I'm using IDE 2.3.2
Is there a different way I should display an address?

void setup() {
  int i = 25;
  int* iPoint;
  Serial.begin (9600);
  iPoint = &i;                  // set the pointer to the address of i
  Serial.print(iPoint);   // try to print the address of i
}

void loop() {
}


--------------- RESULTING COMPILE ERRORS

C:\Users\glenn\AppData\Local\Temp\.arduinoIDE-unsaved2024311-9316-8f90x3.uf3r5\sketch_apr11b\sketch_apr11b.ino: In function 'void setup()':
C:\Users\glenn\AppData\Local\Temp\.arduinoIDE-unsaved2024311-9316-8f90x3.uf3r5\sketch_apr11b\sketch_apr11b.ino:6:22: error: no matching function for call to 'print(int*&)'
   Serial.print(iPoint);   // tru to print the address of i
                      ^
In file included from C:\Users\glenn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino/Stream.h:26:0,
                 from C:\Users\glenn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino/HardwareSerial.h:29,
                 from C:\Users\glenn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino/Arduino.h:233,
                 from C:\Users\glenn\AppData\Local\Temp\arduino\sketches\14ACC17B2B01198D0AFD85BA88983E62\sketch\sketch_apr11b.ino.cpp:1:
C:\Users\glenn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino/Print.h:68:12: note: candidate: size_t Print::print(char) <near match>
     size_t print(char);
            ^~~~~
C:\Users\glenn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino/Print.h:68:12: note:   conversion of argument 1 would be ill-formed:
C:\Users\glenn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino/Print.h:69:12: note: candidate: size_t Print::print(unsigned char, int) <near match>
     size_t print(unsigned char, int = DEC);
            ^~~~~
C:\Users\glenn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino/Print.h:69:12: note:   conversion of argument 1 would be ill-formed:
C:\Users\glenn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino/Print.h:70:12: note: candidate: size_t Print::print(int, int) <near match>
     size_t print(int, int = DEC);
            ^~~~~
C:\Users\glenn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino/Print.h:70:12: note:   conversion of argument 1 would be ill-formed:
C:\Users\glenn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino/Print.h:71:12: note: candidate: size_t Print::print(unsigned int, int) <near match>
     size_t print(unsigned int, int = DEC);
            ^~~~~
C:\Users\glenn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino/Print.h:71:12: note:   conversion of argument 1 would be ill-formed:
C:\Users\glenn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino/Print.h:72:12: note: candidate: size_t Print::print(long int, int) <near match>
     size_t print(long, int = DEC);
            ^~~~~
C:\Users\glenn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino/Print.h:72:12: note:   conversion of argument 1 would be ill-formed:
C:\Users\glenn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino/Print.h:73:12: note: candidate: size_t Print::print(long unsigned int, int) <near match>
     size_t print(unsigned long, int = DEC);
            ^~~~~
C:\Users\glenn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino/Print.h:73:12: note:   conversion of argument 1 would be ill-formed:

exit status 1

Compilation error: no matching function for call to 'print(int*&)'

This works:

void setup() {
  int i = 25;
  int* iPoint;
  Serial.begin (9600);
  iPoint = &i;                  // set the pointer to the address of i
  Serial.print((unsigned int)iPoint);   // try to print the address of i
}

void loop() {
}

Use C++ cast:

Serial.println(reinterpret_cast<uintptr_t> (iPoint));

This did work as did @gfvalvo solution of an explicit cast to type unsigned int pointer

Thanks to both of you. I suspect that @jremington solution will have an issue with other platforms where an address is not an int. I've marked @gfvalvo as the solution because it is more general / platform independent.

Thank you both.
-Glenn

Seems unlikely.

I always wondered about this as well. I always used basically @jremington 's solution but never trusted the answer. Now I tried both of yours, same answer but, both came out 2298

How can this be when a UNO only has 2k of RAM?

Well I tried this..

void setup() {
  int i = 25;
  int j = 32;
  int* iPoint;
  int* jPoint;
  Serial.begin (9600);
  iPoint = &i;                         // set the pointer to the address of i
  jPoint = &j;                         // set the pointer to the address of j
  Serial.println();
  Serial.println((unsigned int)iPoint);  // try to print the address of i
  Serial.println((unsigned int)jPoint);
}

void loop() {
}

And got..
2298
2296

Jumps 2 bytes. That makes sense. Maybe the UNO has a little more than 2K RAM. And they ain't telling us?

-jim lee

Totally impossible in the Arduino environment. In other environments it could be a long int. My current project will never leave home but I try to keep good habits.

SRAM starts at address 0x0100.

AH! Thanks for that.

Part of the neighborhood I tend to not visit.

-jim lee

Actually I was wrong. There seem to be members of the family with a 64k address space rather than a 32k address space. Long is therefore a valid choice depending on the board.

Which, of course, is the whole point of using uintptr_t (Post #3). It's an unsinged integer type that's guaranteed to be large enough to represent any pointer on the platform in question. You don't have to change types when porting code to a different platform.

I'm new to C, C++ and had not seen reinterpret_cast so I went looking.

static_cast is aware of the type of transformation. For example, when converting an int to float there are some calculations required to accomplish the transformation and static_cast provides them. While there is no transformation of the data (an address is the same no matter what it points to) static_cast moves the bit and continues on.

reinterpret_cast seems not to be aware of the type of transformation and simply moves the bits from one location to another. Using it to convert data types would give random results (eg reinterpret_cast from int to float copies the bits but the resulting float value will not equal the original int value except for the special case of 0).

discussion in Stack Overflow quickly got over my head.

Can you tell me why you used reinterpret_cast instead of static_cast?

Thanks,
Glenn

Long story short, static_cast won't compile:

sketch_apr14a:5: error: invalid 'static_cast' from type 'uint32_t*' {aka 'long unsigned int*'} to type 'uintptr_t' {aka 'unsigned int'}
    5 |   Serial.println(static_cast<uintptr_t> (iPoint));
      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
invalid 'static_cast' from type 'uint32_t*' {aka 'long unsigned int*'} to type 'uintptr_t' {aka 'unsigned int'}

a more common approach using %p format option
(see The C Programming Language pg 249)

output:

 val i 25, addr i 0x8fa
void setup() {
    Serial.begin (9600);

    int i = 25;
    int* iPoint;
    iPoint = &i;                  // set the pointer to the address of i

    char s [90];
    sprintf (s, " val i %d, addr i %p", i, iPoint);
    Serial.print (s);
}

void loop() {
}

A very effective argument for not using it. Thanks.

GROAN -- Every time you answer a question I have more reading to do. I'm hoping to eventually get ahead of the game. Thanks for your effort in reeducating an old dog.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.