Thread overview
writefln format specifier for pointers?
Dec 01, 2004
Geoff Hickey
Dec 02, 2004
Sean Kelly
Dec 02, 2004
Geoff Hickey
Dec 02, 2004
pragma
Dec 02, 2004
Geoff Hickey
Dec 03, 2004
Regan Heath
Dec 09, 2004
Geoff Hickey
Dec 09, 2004
Regan Heath
Dec 22, 2004
Geoff Hickey
Dec 03, 2004
Tyro
December 01, 2004
I feel like I'm missing something obvious, but there doesn't seem to be a format specifier that will cause writef to display the value of a pointer. %x, %d, and %s all result in an exception being thrown ("std.format", which is probably coming from format.d line 698.)

Obviously I can cast the pointer to an integral type and use %x, but no one likes unnecessary casts.

Is there a better option, or is this a missing format specifier?

- Geoff


December 02, 2004
In article <coll26$10oi$1@digitaldaemon.com>, Geoff Hickey says...
>
>I feel like I'm missing something obvious, but there doesn't seem to be a format specifier that will cause writef to display the value of a pointer. %x, %d, and %s all result in an exception being thrown ("std.format", which is probably coming from format.d line 698.)
>
>Obviously I can cast the pointer to an integral type and use %x, but no one likes unnecessary casts.
>
>Is there a better option, or is this a missing format specifier?

Try %p


Sean


December 02, 2004
%p works with printf, but not writefln.

- Geoff

In article <colo5r$14of$1@digitaldaemon.com>, Sean Kelly says...
>
>In article <coll26$10oi$1@digitaldaemon.com>, Geoff Hickey says...
>>
>>I feel like I'm missing something obvious, but there doesn't seem to be a format specifier that will cause writef to display the value of a pointer. %x, %d, and %s all result in an exception being thrown ("std.format", which is probably coming from format.d line 698.)
>>
>>Obviously I can cast the pointer to an integral type and use %x, but no one likes unnecessary casts.
>>
>>Is there a better option, or is this a missing format specifier?
>
>Try %p
>
>
>Sean
>
>



December 02, 2004
Just shooting from the hip here, but have you tried "%o"?


In article <coll26$10oi$1@digitaldaemon.com>, Geoff Hickey says...
>
>I feel like I'm missing something obvious, but there doesn't seem to be a format specifier that will cause writef to display the value of a pointer. %x, %d, and %s all result in an exception being thrown ("std.format", which is probably coming from format.d line 698.)
>
>Obviously I can cast the pointer to an integral type and use %x, but no one likes unnecessary casts.
>
>Is there a better option, or is this a missing format specifier?
>
>- Geoff
>
>

- pragma (ericanderton at yahoo)
December 02, 2004
In article <convmv$1kas$1@digitaldaemon.com>, pragma says...
>
>Just shooting from the hip here, but have you tried "%o"?
>
>
I hadn't, so I did, but it didn't work either. Here's a snippet for anyone who wants to see the problem:

int main()
{
int*    p = cast(int*)0xf0d00000;

writefln( "ptr: %o", p );

return 0;
}


December 03, 2004
On Thu, 2 Dec 2004 21:45:32 +0000 (UTC), Geoff Hickey <Geoff_member@pathlink.com> wrote:
> In article <convmv$1kas$1@digitaldaemon.com>, pragma says...
>>
>> Just shooting from the hip here, but have you tried "%o"?
>>
>>
> I hadn't, so I did, but it didn't work either. Here's a snippet for anyone who
> wants to see the problem:
>
> int main()
> {
> int*    p = cast(int*)0xf0d00000;
>
> writefln( "ptr: %o", p );
>
> return 0;
> }

I did a little hacking.. I took the contents of std.format and std.stdio and placed them in a .d file with a main containing only "writefln(cast(void*)0xf0d00000);" this is so I can step into the writef call in MSVC's debugger.

Doing so shows it fails in doFormat on the line:

if (ti.classinfo.name.length < 10)
	    goto Lerror;

ti.classinfo.name is "TypeInfo" and the length is 8, it seems there is no typeinfo for a void *?

Using writefln("%p",cast(void*)0xf0d00000);

causes it to get an array bounds error?! later at these lines:

ti = arguments[j++];
m = cast(Mangle)ti.classinfo.name[9];

I think the above code should read

ti = arguments[j++];
if (ti.classinfo.name.length < 10)
    goto Lerror;
m = cast(Mangle)ti.classinfo.name[9];

or something similar as at this point ti.classinfo.name is "TypeInfo" and the length is 8 as it was in my first case.

It appears to me it's not correctly identifying the type you're trying to print, and/or it has not TypeInfo and does not print. Something like that anyway.

Regan
December 03, 2004
Geoff Hickey wrote:
> I feel like I'm missing something obvious, but there doesn't seem to be a format
> specifier that will cause writef to display the value of a pointer. %x, %d, and
> %s all result in an exception being thrown ("std.format", which is probably
> coming from format.d line 698.)
> 
> Obviously I can cast the pointer to an integral type and use %x, but no one
> likes unnecessary casts.
> 
> Is there a better option, or is this a missing format specifier?
> 
> - Geoff
> 
> 

A workaround maybe?

void main()
{
  uint ui = cast(int*)0xf0d00000;
  uint* pui = &ui;

  writefln("%x",*pui);
  writefln(*pui);
  writefln("%d",*pui);
  writefln("%o",*pui);
  writefln("%b",*pui);
}
December 09, 2004
Regan Heath wrote:
> On Thu, 2 Dec 2004 21:45:32 +0000 (UTC), Geoff Hickey  <Geoff_member@pathlink.com> wrote:
> 
>> In article <convmv$1kas$1@digitaldaemon.com>, pragma says...
>>
>>>
>>> Just shooting from the hip here, but have you tried "%o"?
>>>
>>>
>> I hadn't, so I did, but it didn't work either. Here's a snippet for  anyone who
>> wants to see the problem:
>>
>> int main()
>> {
>> int*    p = cast(int*)0xf0d00000;
>>
>> writefln( "ptr: %o", p );
>>
>> return 0;
>> }
> 
> 
> I did a little hacking.. I took the contents of std.format and std.stdio  and placed them in a .d file with a main containing only  "writefln(cast(void*)0xf0d00000);" this is so I can step into the writef  call in MSVC's debugger.
> 
I had to put this down for awhile, but I dug back into it tonight, following the same path you took.

It seems that the problem is with the TypeInfo instance for pointer types. In particular, I went back to this place (format.d line 528 in dmd v.109):

> Doing so shows it fails in doFormat on the line:
> 
> if (ti.classinfo.name.length < 10)
>         goto Lerror;
> 
> ti.classinfo.name is "TypeInfo" and the length is 8, it seems there is
> no  typeinfo for a void *?
>

and changed it to this (this is *not* a fix, just hacking in a default):

if (ti.classinfo.name.length < 10)
{
	ti.classinfo.name ~= "_P";
}

since by my shallow reading of the dmd code the TypeInfo.classinfo.name string for a pointer should be TypeInfo_P. When I did this, the following code worked:

int main()
{
	int* p = cast(int*)0xf0d00000;

	try
	{
		writefln( p );
		//writefln( "%p", p );
		writefln( "%x", p );
		writefln( "%d", p );
		writefln( "%o", p );
	}
	catch
	{
		writefln( "Blew up!" );
	}

	return 0;
}

It displays:
f0d00000	// no format string
f0d00000	// %x
f0d00000	// %d ??? I was expecting decimal output here, not hex?
36064000000	// %o octal (correct)

It doesn't matter what the pointer type is pointing *to*, by the way, void*, int*, struct* all give the same result (I haven't tried a class instance pointer).

So, I think that there's something wrong with the TypeInfo instances for pointers.  If I've missed something (quite possible) please let me know, otherwise if everyone agrees I'll post this to D.bugs?

Thanks Regan and everyone else who replied for taking the time.

- Geoff Hickey
December 09, 2004
On Thu, 09 Dec 2004 01:23:16 -0500, Geoff Hickey <ardri@comcast.net> wrote:
> Regan Heath wrote:
>> On Thu, 2 Dec 2004 21:45:32 +0000 (UTC), Geoff Hickey  <Geoff_member@pathlink.com> wrote:
>>
>>> In article <convmv$1kas$1@digitaldaemon.com>, pragma says...
>>>
>>>>
>>>> Just shooting from the hip here, but have you tried "%o"?
>>>>
>>>>
>>> I hadn't, so I did, but it didn't work either. Here's a snippet for  anyone who
>>> wants to see the problem:
>>>
>>> int main()
>>> {
>>> int*    p = cast(int*)0xf0d00000;
>>>
>>> writefln( "ptr: %o", p );
>>>
>>> return 0;
>>> }
>>   I did a little hacking.. I took the contents of std.format and std.stdio  and placed them in a .d file with a main containing only  "writefln(cast(void*)0xf0d00000);" this is so I can step into the writef  call in MSVC's debugger.
>>
> I had to put this down for awhile, but I dug back into it tonight, following the same path you took.
>
> It seems that the problem is with the TypeInfo instance for pointer types. In particular, I went back to this place (format.d line 528 in dmd v.109):
>
>> Doing so shows it fails in doFormat on the line:
>>  if (ti.classinfo.name.length < 10)
>>         goto Lerror;
>>
>  > ti.classinfo.name is "TypeInfo" and the length is 8, it seems there is
>  > no  typeinfo for a void *?
>  >
>
> and changed it to this (this is *not* a fix, just hacking in a default):
>
> if (ti.classinfo.name.length < 10)
> {
> 	ti.classinfo.name ~= "_P";
> }
>
> since by my shallow reading of the dmd code the TypeInfo.classinfo.name string for a pointer should be TypeInfo_P. When I did this, the following code worked:
>
> int main()
> {
> 	int* p = cast(int*)0xf0d00000;
>
> 	try
> 	{
> 		writefln( p );
> 		//writefln( "%p", p );
> 		writefln( "%x", p );
> 		writefln( "%d", p );
> 		writefln( "%o", p );
> 	}
> 	catch
> 	{
> 		writefln( "Blew up!" );
> 	}
>
> 	return 0;
> }
>
> It displays:
> f0d00000	// no format string
> f0d00000	// %x
> f0d00000	// %d ??? I was expecting decimal output here, not hex?
> 36064000000	// %o octal (correct)
>
> It doesn't matter what the pointer type is pointing *to*, by the way, void*, int*, struct* all give the same result (I haven't tried a class instance pointer).
>
> So, I think that there's something wrong with the TypeInfo instances for pointers.  If I've missed something (quite possible) please let me know, otherwise if everyone agrees I'll post this to D.bugs?
>
> Thanks Regan and everyone else who replied for taking the time.

You're welcome, I think we should post this to the bugs NG so Walter see's it.
Regan
December 22, 2004
Regan Heath wrote:
> 
> You're welcome, I think we should post this to the bugs NG so Walter see's  it.
> Regan

I thought I'd simplify this a little, since the preceding message doesn't seem to be attracting too much attention. The problem is that writefln can't currently display the values of pointers, unless the pointer is cast to a different type. This problem appears to be caused by the TypeInfo for pointers being incorrect. Here's a simple test case to show this:

int main()
{
	void* test = cast(void*)0xf0d00000;

	TypeInfo ti = typeid( void* );
	ti.print();
	ti = typeid( char[] );
	ti.print();

	return 0;
}

When run, this displays:

TypeInfo
char[]

So the type info for pointers is uninitialized, and this is why writefln is unable to display them. I don't think this is deliberate.

- Geoff Hickey