C99 IDE for windows

C

CBFalconer

Richard said:
arnuld said:
.... snip ...


Then stick with snprintf. In fact, stick with Visual Basic.

Now that is unnecessary nasty treatment of a newbie.
 
C

CBFalconer

Nick said:
[RCH doesn't seem to like snprintf()]
[I must admit its lack of portability puts me off]

What's non-portable? It is specified in the C99 standard.

Assuming the parameters specifying the elements to be printed do
not change between the calls, call snprintf twice. The first time
replace the string with NULL and the size with 0. The returned
value will specify how many chars are needed. Add 1 (for the '\0'
mark), find or make a buffer with that space, and do the second
call.

If the items are likely to change between calls, copy them to
appropriate locations first. Then check and print from those.
 
C

CBFalconer

santosh said:
Richard Heathfield wrote:
.... snip ...


That's the ideal. But assuming that 'pereges' cannot do that
(since if he could, he obviously wouldn't be misusing getch like
this), getchar provides the behaviour he needs (block just before
return from main) without rendering the code nonportable.

He can. He just hasn't learned how.
 
S

santosh

CBFalconer said:
He can. He just hasn't learned how.

Perhaps, but teaching him to open a shell is off-topic for this group,
as is getch(), hence the advise to use getchar().
 
K

Kenny McCormack

Perhaps, but teaching him to open a shell is off-topic for this group,
as is getch(), hence the advise to use getchar().

There you have it gentlemen. What more evidence do you need?

(For those of you slow on the uptake: The "it" is proof that the regs
and wannabees [santosh] would far, far rather give totally worthless and
incomprehensible [to newbies] advice, than give a useful "off-topic"
answer.)
 
K

Keith Thompson

Richard Heathfield said:
santosh said: [...]
Of course the 'p' specifier throws an additional spanner into the works.

I think it throws a spanner into snprintf's works, too - I could be wrong,
but is there any *obligation* on implementations to choose the same
textual representation for a pointer on every invocation? If not, then
snprintf's "let me tell you how big a buffer you would have needed *this*
time" doesn't really mean a lot where %p is concerned.

There's no portable way to determine the maximum length of the result
of a "%p" *printf conversion.

With snprintf, you can make a reasonable guess. The consequence of
guessing wrong is that the resulting string is truncated, and you can
either accept that or try again with a bigger buffer. Even if you're
given an even bigger string on the second attempt, the consequences
are still no worse than a truncated result.

With sprintf, you can make a reasonable guess, but the consequence of
guessing wrong is undefined behavior.

And even for integer and floating-point arguments, where you can (I
think) portably determine the maximum length, getting it right is
still a tedious and error-prone process.
 
S

santosh

Richard said:
santosh said:


Okay, so let's take the classic example of unspecified behaviour -
order of evaluation. The Standard doesn't impose an ordering of any
kind, and therefore implicitly provides gazillions of possible
orderings. Implementations are free to do what they like, and don't
have to document it.

Hmm, so for this instance of unspecified behaviour the Standard omits
specifying directly one or more possibilities, and thus *all*
possibilities are implicitly specified, subject only to the constraints
and the syntax of the language. Okay, I think I get it.
By extension, here the Standard provides (possibly a subset of)
infinitely many possibilities, but requires the implementation to
document its choice. For example, for UINT_MAX the Standard requires
that it's an integer constant AND has a value that is at least 65535
AND (IIRC) is a power-of-two-less-one, but that still leaves
infinitely many possibilities.

So, in effect, an implementation must chose one particular value from a
set of values for UINT_MAX implicitly allowed by the Standard, by not
specifying one or more particular values, but simply a limit and some
related rules.
Implementations are perfectly free to
document this choice along lines such as "if the -foo switch is set,
UINT_MAX is 131071, otherwise if -bar is set it's 262143, otherwise
it's 37778931862957161709567".

Wouldn't that actually make them three different implementations, in
effect?
For iscntrl, implementations are free
to specify just about anything they like as a control character, and I
can find no prohibition on this choice being made dynamically, as long
as the rules are clearly specified (i.e. the implementation documents
how the choice is made).

But these rules themselves should remain constant for any single
invocation of the implementation. Is that right.

So by that reasoning, if I'm correct (and I don't think I am),
implementations can specify a "dynamic rule" or a set of such rules
whereby the value of the constants in limit.h can vary from one
instance of time to another, even within a single invocation of the
implementation (by which I'm including both the translation and
execution environment, and the execution of the program image too)? Is
this logic sound?
3.4
1 behavior
external appearance or action

Here "unspecified value" is not defined, as far as I can see. However
for each instance of unspecified behaviour it seems that the Standard
provides all possible courses of action and the implementation is
merely required to choose one course from this list,

But the Standard may, instead of providing all possible courses of
action, define a rule that places a constraint on the choice (or
several such rules). UINT_MAX is a good example of this. As long as
the implementation obeys those rules, it is free to use further rules
of its own, which need not be static ("the value is X") but could
instead be dynamic ("the value is a consequence of the application of
such-and-such rules with such-and-such parameters, subject to the
[normally minimal] limitations imposed by the Standard").

Okay. So unspecified behaviour essentially means that the Standard
either specifies N possibilities (where N >= 2), or specifies one or
more constraints (must they only be constraints?), which when applied
to the construct yield N possible behaviours?

But for each instance of unspecified behaviour, somehow or the other, N
forms of allowable courses of action must be derived, where N must be
two or more. Specifying just one form of behaviour (this then
becomes "defined") or not specifying any behaviour, either directly or
through constraints (undefined behaviour) is not allowed.
In light of this interpretation (though I'm sure I've overlooked
something important somewhere),

I think you've overlooked the point that the range of possible
behaviours doesn't actually have to be written down anywhere in the
Standard for it to constitute a valid range. For example, the Standard
doesn't have to say: "The value of UINT_MAX shall be 65535 OR 131071
OR 262143 OR 524287 OR ... [snip infinitely many possibilities]..." -
and a good job too, or it would have to have infinitely many pages.

<snip>

But the forms of behaviour must be derivable, or otherwise, it would be
undefined.

So, in view of all this, how is one, as an implementor, to derive the
valid forms of behaviour for the implementation defined output for
the 'p' type specifier in printf? The final choice of the
implementation must be one from a set of 2 to N choices that the
Standard must specify literally or implicitly through it's constraints.
But what constraints can one apply to this case? Any ideas?
 
K

Keith Thompson

Richard Heathfield said:
santosh said:

What's wrong with:

open a shell, find the program, run the program from the shell.

Or find an option in the IDE that tells it not to close the output
window when the program finishes.
 
K

Keith Thompson

santosh said:
Richard Heathfield wrote: [...]
Implementations are perfectly free to
document this choice along lines such as "if the -foo switch is set,
UINT_MAX is 131071, otherwise if -bar is set it's 262143, otherwise
it's 37778931862957161709567".

Wouldn't that actually make them three different implementations, in
effect?

Yes, I believe it would. And writing code to allow for any of those
possibilities is just an example of writing code that's portable to
several implementations.

[...]
But the forms of behaviour must be derivable, or otherwise, it would be
undefined.

So, in view of all this, how is one, as an implementor, to derive the
valid forms of behaviour for the implementation defined output for
the 'p' type specifier in printf? The final choice of the
implementation must be one from a set of 2 to N choices that the
Standard must specify literally or implicitly through it's constraints.
But what constraints can one apply to this case? Any ideas?

C99 7.19.6.2p8:

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

So the constraint (not a "Constraint", just a plain old constraint) is
that the result must be a sequence of printing characters.
 
C

CBFalconer

Keith said:
.... snip ...

There's no portable way to determine the maximum length of the result
of a "%p" *printf conversion.

With snprintf, you can make a reasonable guess. The consequence of
guessing wrong is that the resulting string is truncated, and you can
either accept that or try again with a bigger buffer. Even if you're
given an even bigger string on the second attempt, the consequences
are still no worse than a truncated result.

I disagree, and published the following elsethread:

Assuming the parameters specifying the elements to be printed do
not change between the calls, call snprintf twice. The first time
replace the string with NULL and the size with 0. The returned
value will specify how many chars are needed. Add 1 (for the '\0'
mark), find or make a buffer with that space, and do the second
call.

If the items are likely to change between calls, copy them to
appropriate locations first. Then check and print from those.
 
K

Keith Thompson

Richard Heathfield said:
Keith Thompson said: [...]
With sprintf, you can make a reasonable guess, but the consequence of
guessing wrong is undefined behavior.

If we're allowed a preliminary length-determining operation (as in your
first call to snprintf), we can use fprintf to write the pointer's text
representation to a temporary file and, at the same time, find out how
long it is; then we can seek back in the file and read from the file into
the string. Easy.

Um, sure. It seems unlikely that anyone would do that in real-world
code. Creating a new file is likely to have have substantially
greater overhead than whatever in-memory formatting is done for "%p".

If I don't want to assume the existence of snprintf, I'm likely to
declare a buffer that I can be *reasonably* sure is bigger than any
string I'm going to write to it. I might even compare the result of
sprintf to the size of the buffer; yes, I've already invoked undefined
behavior at that point, but it can't hurt and it's *likely* to give me
a meaningful answer. The memory I've just clobbered past the end of
the buffer *probably* won't interfere with the comparison -- unless it
crashes the program immediately.

Using fprintf to write to a temporary file is one of those solutions
that's 100% portable rather than 99.9% portable, but at the cost of
substantial performance penalties. It reminds me of using a busy loop
with a call to time() to simulate a system-specific sleep() function.
No, not really. We can say "our application is required to support values
in such-and-such a range, so we'll do that, and perhaps provide a bit of
leeway, and then we'll treat anything that won't fit as an exception to be
reported upon and investigated, but in the meantime we're not going to
accept it as part of our string". We have to do this anyway for other
reasons - for example, if we're dealing with ages of living humans we
don't bother supporting ages of, say, 1000+ - so we range-check it and use
%3d and don't care that our super-amazing-ints can hold 85-digit values
because we still only spec three bytes for the text rep of the age value.
(Yes, I know we need one more for the null character.) If we come across
an age of 1000+, we flag that record as needing attention and we move on
to other things /without/ printing it.

Unless the routine in question is fairly low-level, and is just
printing a value of type int, or long, or double, without knowing what
it means. Then you have to *manually* calculate the maximum length of
the result of each conversion, and add them all up -- and get a buffer
overflow anyway because you forgot to carry the 1 and there's no way
the compiler can catch your mistake. It's like Fortran's old
Hollerith constants, only worse.

That's why snprintf was invented. And if you can't depend on your
implementation providing it, you can always grab an open source
version, change the name, and include it in your code.
 
C

Chris Torek

Um, sure. It seems unlikely that anyone would do that in real-world
code.

I have done it.
Creating a new file is likely to have have substantially
greater overhead than whatever in-memory formatting is done for "%p".

I created the file only once, opening it in "w+" mode and doing
rewind() each time I re-used it.

The inner part of the engine ended up looking something like this:

static FILE *temp_file;

... some code goes here to create the temp file ...

char *mallocating_vsprintf(size_t maxlen, const char *fmt, va_list ap) {
int len;
size_t r;
char *result;

if (temp_file == NULL)
init_temp_file(); /* note, not allowed to fail */

rewind(temp_file);
len = vfprintf(temp_file, fmt, ap);
if (len < 0 || fflush(temp_file))
... handle error ...

if (maxlen != 0 && len > maxlen)
len = maxlen;

result = malloc(len + 1);
if (result == NULL)
... handle error ...

rewind(temp_file);
r = fread(result, 1, len, temp_file);
if (r != len)
... handle error ...

result[len] = '\0'; /* terminate string */
return result;
}

(I forget whether the maxlen parameter was always required; this
version accepts 0 to mean "as big as it came out to be". I also
forget how I handled the various error cases. It is possible I
was implementing snprintf() itself, rather than a malloc()-ing
vsnprintf; in this case the malloc step is unnecessary.)
Using fprintf to write to a temporary file is one of those solutions
that's 100% portable rather than 99.9% portable, but at the cost of
substantial performance penalties.

It turned out not to be a problem with what I was doing (which was
a version of Gosling Emacs). The limited-length printing was used
mostly for interactive operation, where "performace" was mainly
limited by the user typing, rather than the computer computing.
 
S

s0suk3

Keith Thompson said:



If we're allowed a preliminary length-determining operation (as in your
first call to snprintf), we can use fprintf to write the pointer's text
representation to a temporary file and, at the same time, find out how
long it is; then we can seek back in the file and read from the file into
the string. Easy.


No, not really. We can say "our application is required to support values
in such-and-such a range, so we'll do that, and perhaps provide a bit of
leeway, and then we'll treat anything that won't fit as an exception to be
reported upon and investigated, but in the meantime we're not going to
accept it as part of our string". We have to do this anyway for other
reasons - for example, if we're dealing with ages of living humans we
don't bother supporting ages of, say, 1000+ - so we range-check it and use
%3d and don't care that our super-amazing-ints can hold 85-digit values
because we still only spec three bytes for the text rep of the age value.
(Yes, I know we need one more for the null character.) If we come across
an age of 1000+, we flag that record as needing attention and we move on
to other things /without/ printing it.

Seems like it's a bit hard to reason with Richard, so let's move onto
practice a bit...

Coincidentally, just a while ago I found myself using snprintf() in a
program to turn a number into a string:

....
size_t serviceLen = 5;
char *service = malloc(sizeof(char) * serviceLen);
if (service == NULL)
return FTT_ERROR_OUT_OF_MEMORY;

while (snprintf(service, serviceLen, "%d", port) >= serviceLen) {
serviceLen += 5;
char *new = realloc(service, sizeof(char) * serviceLen);
if (new == NULL) {
free(service);
return FTT_ERROR_OUT_OF_MEMORY;
}

service = new;
}
....

(Sorry for the undefined identifiers--it's part of a larger codebase.
Oh, 'port' is an integer, BTW). Would you be so kind as to modify this
code snippet so that it doesn't use snprintf() or vsnprintf()? And
let's see how "easy" it is to do it by writing to a temporary file or
checking maximum integer widths.

Sebastian
 
K

Keith Thompson

CBFalconer said:
Keith Thompson wrote:
... snip ...

I disagree, and published the following elsethread:

Assuming the parameters specifying the elements to be printed do
not change between the calls, call snprintf twice. The first time
replace the string with NULL and the size with 0. The returned
value will specify how many chars are needed. Add 1 (for the '\0'
mark), find or make a buffer with that space, and do the second
call.

If the items are likely to change between calls, copy them to
appropriate locations first. Then check and print from those.

Right, but I'm not sure what you're disagreeing with.

You're suggesting a slightly different approach than I am, but I think
both are valid. Your approach always requires calling snprintf twice,
once to determine the required length, and again to store the actual
string. My approach guesstimates the required size. If the guess is
right, you only need one call; if you guessed wrong, call snprintf
again with a bigger buffer.

The qualification "Even if you're given an even bigger string on the
second attempt" was intended to cover the unlikely case where "%p"
with the same argument gives a longer string on the second call than
on the first. Even in that bizarre circumstance, snprintf still
avoids a buffer overflow.
 
M

Martien Verbruggen

Nick said:
[RCH doesn't seem to like snprintf()]
[I must admit its lack of portability puts me off]

What's non-portable? It is specified in the C99 standard.

Assuming the parameters specifying the elements to be printed do
not change between the calls, call snprintf twice.
^^^^^^^^

I think you may have missed the point of the question.

Martien
 
C

CBFalconer

Keith said:
Right, but I'm not sure what you're disagreeing with.

I disagreed with the first quoted sentence. If the pointer doesn't
change, its representation cannot change, since the representation
has to be capable of external storage, reading in with scanf, and
thus recreating the exact original pointer.
 
C

CBFalconer

Martien said:
^^^^^^^^
I think you may have missed the point of the question.

You can always replace the second call to snprintf with a call to
sprintf. The method answers Mr Keighleys 'how' response.
 
S

santosh

CBFalconer said:
You can always replace the second call to snprintf with a call to
sprintf. The method answers Mr Keighleys 'how' response.

I think that Nick Keighley was questioning how one would determine the
storage needed in the *absence* of snprintf (this is because Richard
Heathfield's numbered points were explaining the steps necessary to
correctly use sprintf, which implies that snprintf is not available for
use, for one reason or another.) And the answer was given by Richard
earlier in the thread: use fprintf with a temporary file and read back
the characters written (and match with the return value to be doubly
sure), then allocate the necessary storage for sprintf.

One disadvantage of this method is that it is not usable if the
environment of your program (i.e., the OS) does not allow the creation
of disk files, but only the access of existing ones. This would be the
case when the underlying filesystem is on a read-only media, as it
sometimes is. This doesn't render the C implementation non-conforming,
but it does mean that tmpfile might fail. Using snprintf avoids this
problem.
 
C

CBFalconer

santosh said:
CBFalconer wrote:
.... snip ...


I think that Nick Keighley was questioning how one would determine
the storage needed in the *absence* of snprintf (this is because
Richard Heathfield's numbered points were explaining the steps
necessary to correctly use sprintf, which implies that snprintf is
not available for use, for one reason or another.) And the answer
was given by Richard earlier in the thread: use fprintf with a
temporary file and read back the characters written (and match
with the return value to be doubly sure), then allocate the
necessary storage for sprintf.

In that case I suggest using the %n feature in the format string.

7.19.6 Formatted input/output functions

[#1] The formatted input/output functions217) shall behave
as if there is a sequence point after the actions associated
with each specifier.

____________________

217The printf functions perform writes to memory for the %n
specifier.

.... snip ...

n The argument shall be a pointer to signed integer
into which is written the number of characters
written to the output stream so far by this call to
fprintf. No argument is converted, but one is
consumed. If the conversion specification includes
any flags, a field width, or a precision, the
behavior is undefined.

.... snip ...

7.19.6.6 The sprintf function

Synopsis
[#1]
#include <stdio.h>
int sprintf(char * restrict s,
const char * restrict format, ...);

Description

[#2] The sprintf function is equivalent to fprintf, except
that the output is written into an array (specified by the
argument s) rather than to a stream. A null character is
written at the end of the characters written; it is not
counted as part of the returned value. If copying takes
place between objects that overlap, the behavior is
undefined.

It may be that %n is not available in C90. If so the above is
hogwash.
 
S

santosh

CBFalconer said:
In that case I suggest using the %n feature in the format string.

<snip>

For [v]printf and [v]sprintf the %n feature is useless, because if the
buffer was not large enough, buffer overrun would already have occured
by the time the %n is encountered, and thus further correctness cannot
be relied upon.

For [v]fprintf the %n feature does exactly the same thing as the return
value (provided it is last in the format string of course), but is more
cumbersome to use, and I may be wrong, but I think it cannot be easily
used vfprintf anyway.
 

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
473,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top