Is My Program OK?

K

kooladi

jaysome said:
On Tue, 26 Feb 2008 15:19:33 -0500, Kenneth Brody
CBFalconer wrote:
Kenneth Brody wrote:
(e-mail address removed) wrote:
[... size needed for "%p" output ...]
You *cannot* know the size.
<pedant>
Well, you can "know" it at runtime, with snprintf():
7.19.6.5p3
The snprintf function returns the number of characters that
would have been written had n been sufficiently large, not
counting the terminating null character, or a negative value
if an encoding error occurred.
</pedant>
The C standard for fprintf says:
[... returns length or negative for error ...]
and for printf says:
[... returns length or negative for error ...]
which seem to provide an adequate means of determining the size
written. Similarly for sprintf. Amazingly enough, these also
allow detecting i/o errors in the output stream.
But, how big should you make the buffer for sprintf(), as the OP
was using?
The C Standard says this about the "%p" conversion specification:
"The argument shall be a pointer to void. The value of the pointer is
converted to a sequence of printing characters, in an
implementation-defined manner."
This means that this program:
#include <stdio.h>
int main(void)
{
printf("%p\n", (void*)0);
return 0;
}
can produce the following output in a strictly conforming
implementation:
The quick brown fox jumps over the lazy dog.
It could also output the text of The Declaration of Independence or of
the book War and Peace. In other words, strictly speaking, the answer
to the OP's question is: we don't know and we can't say.
Practically speaking, though, a buffer size that is a generous power
of 2 will work. I'd be comfortable with s[16], but personally I'd use
a very cheap s[32] just for good measure.
In my experience, sprintf'ing a pointer value to a string (in, for
example, a debug log message), requires that you use a size for the
string that is sufficient in size by eyeballing it. For example:
char s[128];
sprintf("p is %p\n", (void*)p);
Although the size 128 is, strictly speaking, not guaranteed to be
sufficient in size to accomodate the "%p" conversion specification
along with the accompanying text, it is sufficient for practical
purposes, all things considered.

I suppose the proper way to do this is:

char *ptr = "hello";
Shouldnt this be const char* ptr="hello";
 
R

Richard Heathfield

santosh said:
jaysome wrote:


I suppose the proper way to do this is:

char *ptr = "hello";
char *a;
int n = snprintf(NULL, 0, "%p", ptr);

It can, of course, be done without snprintf, for those who must avoid that
function for portability reasons - albeit not terribly elegantly. The
obvious way is to use a temporary file and fprintf:

int n = 0;
FILE *fp = tmpfile();
if(tmpfile != NULL)
{
n = fprintf(fp, "%p", (void *)ptr);
fclose(fp);
}
if(n > 0)
{
n + 1 tells us how many bytes to malloc for the string.
 
K

Kenneth Brody

jaysome said:
CBFalconer said:
Kenneth Brody wrote:
(e-mail address removed) wrote:
[... size needed for "%p" output ...]
You *cannot* know the size.

<pedant>
Well, you can "know" it at runtime, with snprintf():

7.19.6.5p3

The snprintf function returns the number of characters that
would have been written had n been sufficiently large, not
counting the terminating null character, or a negative value
if an encoding error occurred.
</pedant>

The C standard for fprintf says:
[... returns length or negative for error ...]
and for printf says:
[... returns length or negative for error ...]
which seem to provide an adequate means of determining the size
written. Similarly for sprintf. Amazingly enough, these also
allow detecting i/o errors in the output stream.

But, how big should you make the buffer for sprintf(), as the OP
was using?

The C Standard says this about the "%p" conversion specification:

"The argument shall be a pointer to void. The value of the pointer is
converted to a sequence of printing characters, in an
implementation-defined manner."

This means that this program:

#include <stdio.h>
int main(void)
{
printf("%p\n", (void*)0);
return 0;
}

can produce the following output in a strictly conforming
implementation:

The quick brown fox jumps over the lazy dog. [...]
Although the size 128 is, strictly speaking, not guaranteed to be
sufficient in size to accomodate the "%p" conversion specification
along with the accompanying text, it is sufficient for practical
purposes, all things considered.

Or, you could do as I pointed out -- use snprintf() to tell you how
long the output will be. (Something which can't be done with CBF's
suggestion of fprintf/printf/sprintf, since those will only tell you
after the fact, not before.)

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
C

CBFalconer

Kenneth said:
.... snip ...

Or, you could do as I pointed out -- use snprintf() to tell you
how long the output will be. (Something which can't be done
with CBF's suggestion of fprintf/printf/sprintf, since those
will only tell you after the fact, not before.)

Or you can design code with one of my favorite tricks - if the
destination is NULL do everthing, and return the result, without
actually outputting anything. That way the equivalent of
"fprintf(NULL, ...)" would return the size required.
 
S

santosh

CBFalconer said:
You can know in advance the max length of most fields to be
written. For strings, you can apply strlen. If you have room to
absorb the max, you can always measure what was actually emitted.

Yes, but the case in question involves finding out how many characters
would be emitted for a pointer value printed out with the %p specifier,
which the Standard doesn't say anything about.

The easiest way to do this without any I/O at all is with snprintf.
Otherwise Richard's solution involving a temporary file and fprintf is
neat as well, since a file cannot (practically) cause a buffer
overflow. It *could* fill up the disk, but it will be immediately
deleted after storing and checking fprintf's return value.

The other option is to print the pointer value as an array of unsigned
char.
 
K

Keith Thompson

CBFalconer said:
Kenneth Brody wrote:
... snip ...

Or you can design code with one of my favorite tricks - if the
destination is NULL do everthing, and return the result, without
actually outputting anything. That way the equivalent of
"fprintf(NULL, ...)" would return the size required.

Just what did you vahe in mind as being equivalent to
"fprintf(NULL, ...)"? It would be nice if fprintf worked that way,
but it doesn't.
 
K

Kenneth Brody

Keith said:
Just what did you vahe in mind as being equivalent to
"fprintf(NULL, ...)"? It would be nice if fprintf worked that way,
but it doesn't.

What's wrong with "snprintf(NULL,0,...)", which does exactly what
we are trying to accomplish -- determine how long the output would
be if it were actually output?

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
W

William Pursell

jaysome wrote:


Is there a guarantee that two calls to printf will produce
the same output? IOW, if we follow santosh's suggestion of:
char *ptr = "hello";
char *a;
int n = snprintf(NULL, 0, "%p", ptr);
if (n > 0) {
a = malloc(n + 1);
if (!a) exit(EXIT_FAILURE);
else {
int m;
m = snprintf(a, n + 1, "%p", ptr);
if (m < 0 || m < n) {
/* error */
}
}}

Is there any guarantee that n + 1 is enough?
Perhaps the first snprintf returns enough space
to write "the quick brown fox", but the
second attempts to print the Declaration of
Independence.
 
C

CBFalconer

Keith said:
Just what did you vahe in mind as being equivalent to
"fprintf(NULL, ...)"? It would be nice if fprintf worked that
way, but it doesn't.

Something you write. Imagine:

size_t foo(/* things */, FILE *f) {
....
if (f) err |= putc(f);
...
return something;
}

I have some routines to convert numbers to chars so written.
 
B

Bartc

William Pursell said:
Is there a guarantee that two calls to printf will produce
the same output? IOW, if we follow santosh's suggestion of:
....

Is there any guarantee that n + 1 is enough?
Perhaps the first snprintf returns enough space
to write "the quick brown fox", but the
second attempts to print the Declaration of
Independence.

They have to be the same. If not then it makes printing %p more or less
impossible in a reliable way.

Unless you print to a file first, but that starts becoming a crazy way to do
this.

The standard should have specified an upper limit for %p format length.
 
M

Micah Cowan

Bartc said:
They have to be the same. If not then it makes printing %p more or less
impossible in a reliable way.

This, however, is a QoI issue, and not a mandate from the standard. A
nasty-but-conforming implementation could print %p differently for the
samve value on a second call.
 

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

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top