outputting a NULL pointer to a stream

J

Jacek Dziedzic

Hello!

I have a piece of code that needs to display a formatted
table of pointers using streams, with the pointers represented
as hex values. It looks more or less like this:

#include <iostream>
#include <iomanip>

using namespace std;

// ptr[] is an array of pointers

int main() {
for(unsigned int i=0;i<some_size;++i) {

cout << hex << setprecision(16) << setw(20)
<< (void*)ptr << '\n';

}

}

What annoys me is that if ptr is NULL, then it does
get output as ' 0' instead of
'0x0000000000000000' as I'd like it to print.

Can anyone suggest a solution to this, other than
checking for NULL manually? Casting to int is not an
option since pointers are 8-byte and ints are 4-byte
on my system.

thanks in advance,
- J.
 
M

mlimber

Jacek said:
Hello!

I have a piece of code that needs to display a formatted
table of pointers using streams, with the pointers represented
as hex values. It looks more or less like this:

#include <iostream>
#include <iomanip>

using namespace std;

// ptr[] is an array of pointers

int main() {
for(unsigned int i=0;i<some_size;++i) {

cout << hex << setprecision(16) << setw(20)
<< (void*)ptr << '\n';

}

}

What annoys me is that if ptr is NULL, then it does
get output as ' 0' instead of
'0x0000000000000000' as I'd like it to print.

Can anyone suggest a solution to this, other than
checking for NULL manually? Casting to int is not an
option since pointers are 8-byte and ints are 4-byte
on my system.

thanks in advance,
- J.


Use std::cout::fill( '0' ) or the equivalent I/O manipulator. I'll bet
a pointer to, say, address 0x100 also prints without the zeros (i.e., '
100'). BTW, you omitted the "0x" in your cout
statement.

M
 
J

Jacek Dziedzic

mlimber said:
>
> Use std::cout::fill( '0' ) or the equivalent I/O manipulator. I'll bet
> a pointer to, say, address 0x100 also prints without the zeros (i.e., '
> 100'). BTW, you omitted the "0x" in your cout
> statement.

You've lost your bet :). Since I've used std::hex, the
pointers print out as (for instance)

0x2000000002affc00
0x2000000007ccda34
0x2000000009418afb
0
0x2000000009418afb
0x2000000009418afb

etc.

without having to manually specifying "0x" and setting the fill-char
to "0". But not for NULL, alas.

- J.
 
J

Jim Langston

Jacek Dziedzic said:
You've lost your bet :). Since I've used std::hex, the
pointers print out as (for instance)

0x2000000002affc00
0x2000000007ccda34
0x2000000009418afb
0
0x2000000009418afb
0x2000000009418afb

etc.

without having to manually specifying "0x" and setting the fill-char
to "0". But not for NULL, alas.

You missed something. Don't you notice the first value is 2? 0x2....
that's why you're not missing any leading zeros, you dont' have any!

So he hasn't lost the bet yet.
 
J

Jacek Dziedzic

Jim said:
You missed something. Don't you notice the first value is 2? 0x2....
that's why you're not missing any leading zeros, you dont' have any!

So he hasn't lost the bet yet.

void *p=(void*)0x100;
void *q=(void*)main; // for instance
void *r=NULL;

cout << fixed << setfill('0');
cout << hex << setprecision(16) << setw(18) << p << '\n';
cout << hex << setprecision(16) << setw(18) << q << '\n';
cout << hex << setprecision(16) << setw(18) << r << '\n';

produces

00000000000000x100
0x4000000000001990
000000000000000000

while I'd like to have

0x0000000000000100
0x4000000000001990
0x0000000000000000

.... so while mliber was right about "a pointer to, say, address
0x100 also prints without the zeros" [without setfill('0')]

he missed the 'hex' issue. Therefore, alas, setfill() does not
help me, or I can't see it helping me.

What I can't understand is, why this special value of NULL
would not print with "0x" in front of it like all other
hex values (for pointers).

Will I *really* need to cast this pointer to two (or more)
int values and output them as hex, followed by "0x" which
I'll have to add manually?

- J.
 
J

John Harrison

Jacek said:
Jim said:
You missed something. Don't you notice the first value is 2? 0x2....
that's why you're not missing any leading zeros, you dont' have any!

So he hasn't lost the bet yet.


void *p=(void*)0x100;
void *q=(void*)main; // for instance
void *r=NULL;

cout << fixed << setfill('0');
cout << hex << setprecision(16) << setw(18) << p << '\n';
cout << hex << setprecision(16) << setw(18) << q << '\n';
cout << hex << setprecision(16) << setw(18) << r << '\n';

produces

00000000000000x100
0x4000000000001990
000000000000000000

while I'd like to have

0x0000000000000100
0x4000000000001990
0x0000000000000000

... so while mliber was right about "a pointer to, say, address
0x100 also prints without the zeros" [without setfill('0')]

he missed the 'hex' issue. Therefore, alas, setfill() does not
help me, or I can't see it helping me.

What I can't understand is, why this special value of NULL
would not print with "0x" in front of it like all other
hex values (for pointers).

Will I *really* need to cast this pointer to two (or more)
int values and output them as hex, followed by "0x" which
I'll have to add manually?

- J.

You might find this helps

cout << hex << setprecision(16) << internal << setw(18) << p << '\n';

john
 
J

Jacek Dziedzic

John said:
You might find this helps

cout << hex << setprecision(16) << internal << setw(18) << p << '\n';

It doesn't, unfortunately. AFAIK 'internal' is used if you
want to have the number aligned right and the sign to the left,
correct? Unfortunately "0x" does not want to behave like a
sign.

I browsed the whole section on manipulators in my Josuttis
book and it doesn't say a word on outputting pointers. Perhaps
the implementation is rather free as to the way it outputs
them?

I'm lost now and the prospect of outputting them converted
in sizeof(char) pieces looms.

thanks,
- J.
 
J

Jim Langston

Jacek Dziedzic said:
It doesn't, unfortunately. AFAIK 'internal' is used if you
want to have the number aligned right and the sign to the left,
correct? Unfortunately "0x" does not want to behave like a
sign.

I browsed the whole section on manipulators in my Josuttis
book and it doesn't say a word on outputting pointers. Perhaps
the implementation is rather free as to the way it outputs
them?

I'm lost now and the prospect of outputting them converted
in sizeof(char) pieces looms.

Only thing I could think of would be to somehow print them without the 0x
prefix and add it manually. Don't think there is a flag for that though :/
 
J

Jacek Dziedzic

Jim said:
Only thing I could think of would be to somehow print them without the 0x
prefix and add it manually. Don't think there is a flag for that though :/

I gave up and resorted to:

#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <sstream>

using namespace std;

string ptr_to_str(const void* const ptr) {

// represent the pointer as unsigned char[]
unsigned char ptr_representation[sizeof(void*)];
memcpy(ptr_representation,&ptr,sizeof(void*));

string result;
stringstream ss;
ss << "0x" << hex << setfill('0');

// iterate over the array in a little-endian manner
for(int i=sizeof(void*)-1; i>=0; --i) {
unsigned int k = ptr_representation;
ss << setw(2) << k;
}
ss >> result;
return result;
}

int main() {
void *p=NULL;
void *q=(void*)&main; // for instance
void *r=(void*)0x123; // for instance

cout << ptr_to_str(p) << "\n";
cout << ptr_to_str(q) << "\n";
cout << ptr_to_str(r) << "\n";
}

and this produces

0x0000000000000000
0x4000000000009e60
0x0000000000000123

just as desired, only for little-endian platforms, however.

- J.
 
M

mlimber

Jacek said:
Jim said:
You missed something. Don't you notice the first value is 2? 0x2....
that's why you're not missing any leading zeros, you dont' have any!

So he hasn't lost the bet yet.

void *p=(void*)0x100;
void *q=(void*)main; // for instance
void *r=NULL;

cout << fixed << setfill('0');
cout << hex << setprecision(16) << setw(18) << p << '\n';
cout << hex << setprecision(16) << setw(18) << q << '\n';
cout << hex << setprecision(16) << setw(18) << r << '\n';

produces

00000000000000x100
0x4000000000001990
000000000000000000

while I'd like to have

0x0000000000000100
0x4000000000001990
0x0000000000000000

... so while mliber was right about "a pointer to, say, address
0x100 also prints without the zeros" [without setfill('0')]

he missed the 'hex' issue. Therefore, alas, setfill() does not
help me, or I can't see it helping me.
[snip]

It looks like you have the ios::showbase flag enabled. Try turning that
off, specifying the base indicator yourself, and using fill:

void* p = 0;
cout << hex << noshowbase << "0x" << setfill( '0' )
<< setw( 18 ) << p << endl;

Cheers! --M
 
J

Jacek Dziedzic

mlimber said:
Jacek said:
Jim said:
You missed something. Don't you notice the first value is 2? 0x2....
that's why you're not missing any leading zeros, you dont' have any!

So he hasn't lost the bet yet.

void *p=(void*)0x100;
void *q=(void*)main; // for instance
void *r=NULL;

cout << fixed << setfill('0');
cout << hex << setprecision(16) << setw(18) << p << '\n';
cout << hex << setprecision(16) << setw(18) << q << '\n';
cout << hex << setprecision(16) << setw(18) << r << '\n';

produces

00000000000000x100
0x4000000000001990
000000000000000000

while I'd like to have

0x0000000000000100
0x4000000000001990
0x0000000000000000

... so while mliber was right about "a pointer to, say, address
0x100 also prints without the zeros" [without setfill('0')]

he missed the 'hex' issue. Therefore, alas, setfill() does not
help me, or I can't see it helping me.

[snip]

It looks like you have the ios::showbase flag enabled. Try turning that
off, specifying the base indicator yourself, and using fill:

void* p = 0;
cout << hex << noshowbase << "0x" << setfill( '0' )
<< setw( 18 ) << p << endl;

Ah yes, works like a charm! I didn't know (no)showbase
worked for pointers too. It's not a common manipulator also,
I guess. Your method is much cleaner, although the 18
requires some tuning depending on sizeof(void*).

thanks a lot,
- J.
 
K

Karl Heinz Buchegger

Jacek said:
void *p=(void*)0x100;
void *q=(void*)main; // for instance
void *r=NULL;

cout << fixed << setfill('0');
cout << hex << setprecision(16) << setw(18) << p << '\n';
cout << hex << setprecision(16) << setw(18) << q << '\n';
cout << hex << setprecision(16) << setw(18) << r << '\n';

produces

00000000000000x100
0x4000000000001990
000000000000000000

That's odd.
Will I *really* need to cast this pointer to two (or more)
int values and output them as hex, followed by "0x" which
I'll have to add manually?

Seems so.

If possible, I would also contact the compiler vendor and tell them
about this. It doesn't seem to be right and to be a bug in the
I/O library.
 
J

Jacek Dziedzic

Karl said:
That's odd.




Seems so.

If possible, I would also contact the compiler vendor and tell them
about this. It doesn't seem to be right and to be a bug in the
I/O library.

And what *is* wrong specifically? I checked it with the g++
compiler and got the same output.

And about contacting the compiler vendor... I contacted them
a month ago using their premier support to complain about a
rather serious bug in a well-known implementation of Linear Algebra
PACKage they sell. They have reproduced the bug but seemingly do
not care to fix it, at least not within a month. I guess won't
hassle them with petty things then :).

- J.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,262
Messages
2,571,056
Members
48,769
Latest member
Clifft

Latest Threads

Top