Is My Program OK?

A

Andy G.

Greetings!

I am learning C and I came up with this program to test my knowledge.

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char s[128];
void *p;
sprintf(s, "%p", malloc(0x10));
puts(s);
sscanf(s, "%p", &p);
printf("%p\n", p);
free(p);
return 0;
}

Is it OK? Even if malloc returns NULL?

One thing I am not sure of is what the size of s should be. Is 128
enough? Or too much? How should I know how big to make it?

Thanks in advance -- Andy!
 
V

vippstar

Greetings!

I am learning C and I came up with this program to test my knowledge.

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char s[128];
void *p;
sprintf(s, "%p", malloc(0x10));
puts(s);
sscanf(s, "%p", &p);
printf("%p\n", p);
free(p);
return 0;

}

Is it OK? Even if malloc returns NULL?
Yes, except the sprintf() part.
One thing I am not sure of is what the size of s should be. Is 128
enough? Or too much? How should I know how big to make it?
You cannot know whether it will fit or not.
You should instead use snprintf() and check the return value.
Also, save the pointer somewhere, in case it does not fit in the
buffer so you can free it.
 
V

Vitillo Roberto

You cannot know whether it will fit or not.
Are you sure? This should do the trick:

int mod = -1;
int len = ((mod = sizeof(void*) % sizeof(char)) == 0) ? sizeof(void*)/
sizeof(char) : sizeof(void*)/sizeof(char)+1;
char s[len];
 
B

Bartc

Vitillo Roberto said:
You cannot know whether it will fit or not.
Are you sure? This should do the trick:

int mod = -1;
int len = ((mod = sizeof(void*) % sizeof(char)) == 0) ? sizeof(void*)/
sizeof(char) : sizeof(void*)/sizeof(char)+1;
char s[len];

I think if my life depended on getting len absolutely right, I would rather
take my chances with len=128.

Especially as your code seems to give len=4 :)
 
R

Roberto V.

Ups...
int mod = -1;
int len = ((mod = sizeof(void*)*2 % sizeof(char)) == 0) ?
sizeof(void*)*2/sizeof(char) : sizeof(void*)*2/sizeof(char)+1;
char s[len+1];

Better now? ;)
 
V

vippstar

Ups...
int mod = -1;
int len = ((mod = sizeof(void*)*2 % sizeof(char)) == 0) ?
sizeof(void*)*2/sizeof(char) : sizeof(void*)*2/sizeof(char)+1;
char s[len+1];

Better now? ;)

What logic is that?
Do you have any understanding of the problem I addressed?
sizeof(void *)*2 % sizeof(char) will always 0 because sizeof(char) is
guaranteed to be 1. N % 1 == 0.
So, we completely ignore the first case, and let's see what's after
the ':'
sizeof(void *) * 2 / sizeof (char) + 1
Let us assume sizeof (void *) is 4. 4 * 2 / 1 + 1 = 8 / 1 + 1 = 8 + 1
= 9.
I think I start to understand your logic (which, alas is still flawed)
You want to calculate the N of bytes in the pointer size, so you can
'predict' the size of it's hex representation.
Ofcourse, the mistake here is that you *assume* the representation
will be in hex.
You also assume that EVEN if it's in hex, 0x will not be prefixed.
0xHHHHHHHH is 11 in size and not 9.

You *cannot* know the size.
 
S

santosh

Greetings!

I am learning C and I came up with this program to test my knowledge.

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char s[128];
void *p;
sprintf(s, "%p", malloc(0x10));
puts(s);
sscanf(s, "%p", &p);
printf("%p\n", p);
free(p);
return 0;

}

Is it OK? Even if malloc returns NULL?
Yes, except the sprintf() part.
One thing I am not sure of is what the size of s should be. Is 128
enough? Or too much? How should I know how big to make it?
You cannot know whether it will fit or not.
You should instead use snprintf() and check the return value.
Also, save the pointer somewhere, in case it does not fit in the
buffer so you can free it.

One more minor point is to cast the argument to printf to a void *,
since the %p specifier is defined as accepting a void pointer value
only.

Maybe also change 's' to unsigned char[].
 
V

vippstar

Greetings!
I am learning C and I came up with this program to test my knowledge.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char s[128];
void *p;
sprintf(s, "%p", malloc(0x10));
puts(s);
sscanf(s, "%p", &p);
printf("%p\n", p);
free(p);
return 0;
}
Is it OK? Even if malloc returns NULL?
Yes, except the sprintf() part.
One thing I am not sure of is what the size of s should be. Is 128
enough? Or too much? How should I know how big to make it?
You cannot know whether it will fit or not.
You should instead use snprintf() and check the return value.
Also, save the pointer somewhere, in case it does not fit in the
buffer so you can free it.

One more minor point is to cast the argument to printf to a void *,
since the %p specifier is defined as accepting a void pointer value
only.
That is not needed in the source mr Andy G. posted.
 
B

Ben Bacarisse

santosh said:
On Feb 23, 10:26 am, "Andy G." <[email protected]> wrote:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char s[128];
void *p;
sprintf(s, "%p", malloc(0x10));
puts(s);
sscanf(s, "%p", &p);
printf("%p\n", p);
free(p);
return 0;
}

Is it OK? Even if malloc returns NULL?
One more minor point is to cast the argument to printf to a void *,
since the %p specifier is defined as accepting a void pointer value
only.

In both cases it is a void * that is passed.
 
B

Ben Bacarisse

Vitillo Roberto said:
You cannot know whether it will fit or not.
Are you sure? This should do the trick:

int mod = -1;
int len = ((mod = sizeof(void*) % sizeof(char)) == 0) ? sizeof(void*)/
sizeof(char) : sizeof(void*)/sizeof(char)+1;
char s[len];

Nothing about sizeof(void *) can tell you the required output size.
It could tell you something about the possible number of different
pointer values, but that is not the same thing. %p might produce:

<segment: 0x2345 offset: 2998788765 in cluster main:24>

who knows?
 
S

santosh

Greetings!
I am learning C and I came up with this program to test my
knowledge.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char s[128];
void *p;
sprintf(s, "%p", malloc(0x10));
puts(s);
sscanf(s, "%p", &p);
printf("%p\n", p);
free(p);
return 0;

Is it OK? Even if malloc returns NULL?
Yes, except the sprintf() part.
One thing I am not sure of is what the size of s should be. Is 128
enough? Or too much? How should I know how big to make it?
You cannot know whether it will fit or not.
You should instead use snprintf() and check the return value.
Also, save the pointer somewhere, in case it does not fit in the
buffer so you can free it.

One more minor point is to cast the argument to printf to a void *,
since the %p specifier is defined as accepting a void pointer value
only.
That is not needed in the source mr Andy G. posted.

Ah yes. My bad.
 
K

Kenneth Brody

On Feb 23, 1:45 pm, "Roberto V." <[email protected]> wrote:
[...attempt to calculate length of sprintf's "%p" output...]
Better now? ;)

What logic is that? [...]
You also assume that EVEN if it's in hex, 0x will not be prefixed.
0xHHHHHHHH is 11 in size and not 9.

It also assume that nothing bu the hex digits are output. There
may be other things, like a ':' separating segment:eek:ffset, or any
other assorted decorations.
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>

--
+-------------------------+--------------------+-----------------------+
| 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:
(e-mail address removed) wrote:
.... snip ...


It also assume that nothing bu the hex digits are output. There
may be other things, like a ':' separating segment:eek:ffset, or any
other assorted decorations.


<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

[#14] The fprintf function returns the number of characters
transmitted, or a negative value if an output or encoding
error occurred.

and for printf says:

Returns

[#3] The printf function returns the number of characters
transmitted, or a negative value if an output or encoding
error occurred.

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.
 
P

Peter Nilsson

Andy G. said:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
  char s[128];
  void *p;
  sprintf(s, "%p", malloc(0x10));
  puts(s);
  sscanf(s, "%p", &p);
  printf("%p\n", p);
  free(p);
  return 0;

}

Is it OK? Even if malloc returns NULL?

One thing I am not sure of is what the size of s should
be. Is 128 enough? Or too much? How should I know how
big to make it?

No, yes and this big respectively. :)

Other advice notwithstanding, if you actually want to
print a pointer, even with the possibility of scanning
it back later, then you should print and scan the
representation as an array of unsigned char. The size
(of hex output say) can be computed at compile time.
 
K

Kenneth Brody

CBFalconer said:
Kenneth said:
(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?

--
+-------------------------+--------------------+-----------------------+
| 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

Willem

CBFalconer wrote:
) The C standard for fprintf says:
<snip> (returns the number printed, or negative)
) and for printf says:
<snip>
) which seem to provide an adequate means of determining the size
) written. Similarly for sprintf.

Indeed, you can check that sprintf has gone beyond the bounds of your
buffer. _After_ it has clobbered whatever happened to be located behind
it (or invoked some other form of UB). Oopsie.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
A

Antoninus Twink

CBFalconer said:
Kenneth said:
(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?

You can fprintf it to /dev/null (or NUL), collect the return value, and
then make the buffer that big for sprinf() with the same format string
and arguments.

Of course, that can't be what CBF had in mind as it's off-topic, not
portable, not C, can't discuss it, blah blah.
 
C

CBFalconer

Willem said:
Indeed, you can check that sprintf has gone beyond the bounds of
your buffer. _After_ it has clobbered whatever happened to be
located behind it (or invoked some other form of UB). Oopsie.

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.
 
J

jaysome

CBFalconer said:
Kenneth said:
(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.
 
S

santosh

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.

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";
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 */
}
}
}
else /* error */
 

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,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top