C99 IDE for windows

S

s0suk3

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;
}

...

Never mind. The approach described by CBFalconer is much better. This
is what it would boil down to:

....
int serviceLen = snprintf(NULL, 0, "%d", port);
char service[serviceLen + 1];
snprintf(service, serviceLen, "%d", port);
....

Sebastian
 
S

santosh

(e-mail address removed) wrote:

Never mind. The approach described by CBFalconer is much better. This
is what it would boil down to:

...
int serviceLen = snprintf(NULL, 0, "%d", port);
char service[serviceLen + 1];
snprintf(service, serviceLen, "%d", port);

That should be:

snprintf(service, serviceLen+1, "%d", port);

or the last character will be discarded.
 
V

vippstar

(e-mail address removed) said:

Never mind. The approach described by CBFalconer is much better. This
is what it would boil down to:
...
int serviceLen = snprintf(NULL, 0, "%d", port);
char service[serviceLen + 1];
snprintf(service, serviceLen, "%d", port);

Faster (because it makes only one call to a string-building routine) and
more portable (because it doesn't depend on either VLAs or snprintf) is:

char service[(sizeof(int) * CHAR_BIT + 2) / 3 + 2];
sprintf(service, "%d", port);

Isn't 'service' a VLA? (because of sizeof)
 
S

s0suk3

(e-mail address removed) wrote:

Never mind. The approach described by CBFalconer is much better. This
is what it would boil down to:
...
int serviceLen = snprintf(NULL, 0, "%d", port);
char service[serviceLen + 1];
snprintf(service, serviceLen, "%d", port);

That should be:

snprintf(service, serviceLen+1, "%d", port);

or the last character will be discarded.

Right! Thanks.

Sebastian
 
S

s0suk3

(e-mail address removed) said:

Never mind. The approach described by CBFalconer is much better. This
is what it would boil down to:
...
int serviceLen = snprintf(NULL, 0, "%d", port);
char service[serviceLen + 1];
snprintf(service, serviceLen, "%d", port);

Faster (because it makes only one call to a string-building routine) and
more portable (because it doesn't depend on either VLAs or snprintf) is:

char service[(sizeof(int) * CHAR_BIT + 2) / 3 + 2];
sprintf(service, "%d", port);

What does the operation calculate? If it's the max number of digits
that an int can represent: wouldn't that allocate more space that
might be needed? If not: wouldn't that cause the call to sprintf() to
be insecure?

Sebastian
 
B

Ben Bacarisse

(e-mail address removed) said:

Never mind. The approach described by CBFalconer is much better. This
is what it would boil down to:
...
int serviceLen = snprintf(NULL, 0, "%d", port);
char service[serviceLen + 1];
snprintf(service, serviceLen, "%d", port);

Faster (because it makes only one call to a string-building routine) and
more portable (because it doesn't depend on either VLAs or snprintf) is:

char service[(sizeof(int) * CHAR_BIT + 2) / 3 + 2];
sprintf(service, "%d", port);

Isn't 'service' a VLA? (because of sizeof)

No. 6.6.6:

"An integer constant expression shall have integer type and shall
only have operands 6 that are integer constants, enumeration
constants, character constants, sizeof expressions whose results are
integer constants, and floating constants that are the immediate
operands of casts. Cast operators in an integer constant expression
shall only convert arithmetic types to integer types, except as part
of an operand to the sizeof operator."

You are probably thinking of the expressions allowed in #if. These
can't use sizeof except as an identifier that will be replaced by the
pp-token 0.
 
S

santosh

(e-mail address removed) said:

Never mind. The approach described by CBFalconer is much better.
This is what it would boil down to:
...
int serviceLen = snprintf(NULL, 0, "%d", port);
char service[serviceLen + 1];
snprintf(service, serviceLen, "%d", port);

Faster (because it makes only one call to a string-building routine)
and more portable (because it doesn't depend on either VLAs or
snprintf) is:

char service[(sizeof(int) * CHAR_BIT + 2) / 3 + 2];
sprintf(service, "%d", port);

What does the operation calculate? If it's the max number of digits
that an int can represent: wouldn't that allocate more space that
might be needed?

It might, but that extra space will be trivially small unless your int
happens to be able to hold hundreds or thousands of digits. :)
If not: wouldn't that cause the call to sprintf() to
be insecure?

It isn't, but separate routines will be needed for other bases, or you
might just allocate space for a binary representation and use that for
all other bases.
 
S

santosh

Richard said:
(e-mail address removed) said:
(e-mail address removed) said:

<snip>

Never mind. The approach described by CBFalconer is much better.
This is what it would boil down to:

...
int serviceLen = snprintf(NULL, 0, "%d", port);
char service[serviceLen + 1];
snprintf(service, serviceLen, "%d", port);

Faster (because it makes only one call to a string-building routine)
and more portable (because it doesn't depend on either VLAs or
snprintf) is:

char service[(sizeof(int) * CHAR_BIT + 2) / 3 + 2];
sprintf(service, "%d", port);

Isn't 'service' a VLA? (because of sizeof)

No. The sizeof operator's result is evaluated during translation, and
yields a constant integer expression that you can use to define the
size of an ordinary C90 array.

Sizeof is available during the later stages of translation, but
unfortunately, it's not available during the preprocessing stages.
 
S

santosh

santosh said:
Richard said:
(e-mail address removed) said:
(e-mail address removed) said:

<snip>

Never mind. The approach described by CBFalconer is much better.
This is what it would boil down to:

...
int serviceLen = snprintf(NULL, 0, "%d", port);
char service[serviceLen + 1];
snprintf(service, serviceLen, "%d", port);

Faster (because it makes only one call to a string-building
routine) and more portable (because it doesn't depend on either
VLAs or snprintf) is:

char service[(sizeof(int) * CHAR_BIT + 2) / 3 + 2];
sprintf(service, "%d", port);

Isn't 'service' a VLA? (because of sizeof)

No. The sizeof operator's result is evaluated during translation, and
yields a constant integer expression that you can use to define the
size of an ordinary C90 array.

Sizeof is available during the later stages of translation, but
unfortunately, it's not available during the preprocessing stages.

Sorry. I misdirected this post to you. I meant it for vippstar. Please
ignore.
 
B

Ben Bacarisse

Richard Heathfield said:
(e-mail address removed) said:
On Aug 7, 5:53 am, Richard Heathfield <[email protected]> wrote:
char service[(sizeof(int) * CHAR_BIT + 2) / 3 + 2];
sprintf(service, "%d", port);

What does the operation calculate?

The maximum number of decimal digits an int can represent, plus one for the
sign and one for the null terminator.
wouldn't that allocate more space that might be needed?

It's possible, yes. For example, if CHAR_BIT is 33 (i.e. there are 33 bits
in a byte) and sizeof(int) is 5, with no padding bits and one sign bit, we
have 164 value bits (and 1 sign bit), so INT_MAX is a fifty-digit number
(in fact it's 23384026197294446691258957323460528314494920687615), and my
expression (excluding provision for the sign byte and the null byte)
yields 166 / 3 = 55, so a massive five bytes are wasted.

I suspect he's worrying about the 54 wasted bytes when converting 0.
To s0suk3: use the return from sprintf to malloc the correct space.
In your original you wanted a freeable return value, so this local
array is always going to be just a temporary buffer.
 
S

s0suk3

(e-mail address removed) said:


(e-mail address removed) said:
int serviceLen = snprintf(NULL, 0, "%d", port);
char service[serviceLen + 1];
snprintf(service, serviceLen, "%d", port);
Faster (because it makes only one call to a string-building routine) and
more portable (because it doesn't depend on either VLAs or snprintf) is:
char service[(sizeof(int) * CHAR_BIT + 2) / 3 + 2];
sprintf(service, "%d", port);
What does the operation calculate?

The maximum number of decimal digits an int can represent, plus one for the
sign and one for the null terminator.
If it's the max number of digits
that an int can represent:
Right.

wouldn't that allocate more space that might be needed?

It's possible, yes. For example, if CHAR_BIT is 33 (i.e. there are 33 bits
in a byte) and sizeof(int) is 5, with no padding bits and one sign bit, we
have 164 value bits (and 1 sign bit), so INT_MAX is a fifty-digit number
(in fact it's 23384026197294446691258957323460528314494920687615), and my
expression (excluding provision for the sign byte and the null byte)
yields 166 / 3 = 55, so a massive five bytes are wasted.

Feel free to devise a better algorithm, bearing in mind that you can't take
logs or do anything else that involves runtime evaluation (because
otherwise it won't be a constant integer expression and therefore it won't
be suitable for sizing a C90 array).

Why does it have to be a C90 array? You can always use either a VLA,
or malloc() if you don't have access to a C99 compiler (unlikely). As
for calculating the required length, I don't think there's a better or
more elegant way than calling snprintf() twice (which I don't think
imposes much overhead, do you?).

<snip>

Sebastian
 
V

vippstar

char service[(sizeof(int) * CHAR_BIT + 2) / 3 + 2];
sprintf(service, "%d", port);
Isn't 'service' a VLA? (because of sizeof)

No. 6.6.6:

"An integer constant expression shall have integer type and shall
only have operands 6 that are integer constants, enumeration
constants, character constants, sizeof expressions whose results are
integer constants, and floating constants that are the immediate
operands of casts. Cast operators in an integer constant expression
shall only convert arithmetic types to integer types, except as part
of an operand to the sizeof operator."

You are probably thinking of the expressions allowed in #if. These
can't use sizeof except as an identifier that will be replaced by the
pp-token 0.

Ah thanks. Now that santosh mentioned the value being available in
later TPs it makes more sense to me.

6.6.6 :)
 
S

santosh

(e-mail address removed) said:


(e-mail address removed) said:
int serviceLen = snprintf(NULL, 0, "%d", port);
char service[serviceLen + 1];
snprintf(service, serviceLen, "%d", port);
Faster (because it makes only one call to a string-building
routine) and more portable (because it doesn't depend on either
VLAs or snprintf) is:
char service[(sizeof(int) * CHAR_BIT + 2) / 3 + 2];
sprintf(service, "%d", port);
What does the operation calculate?

The maximum number of decimal digits an int can represent, plus one
for the sign and one for the null terminator.
If it's the max number of digits
that an int can represent:
Right.

wouldn't that allocate more space that might be needed?

It's possible, yes. For example, if CHAR_BIT is 33 (i.e. there are 33
bits in a byte) and sizeof(int) is 5, with no padding bits and one
sign bit, we have 164 value bits (and 1 sign bit), so INT_MAX is a
fifty-digit number (in fact it's
23384026197294446691258957323460528314494920687615), and my
expression (excluding provision for the sign byte and the null byte)
yields 166 / 3 = 55, so a massive five bytes are wasted.

Feel free to devise a better algorithm, bearing in mind that you
can't take logs or do anything else that involves runtime evaluation
(because otherwise it won't be a constant integer expression and
therefore it won't be suitable for sizing a C90 array).

Why does it have to be a C90 array?

So that you don't have to be worried about portability.
You can always use either a VLA, or malloc()

True, but this involves writing conditional code with #if #else #endif,
which is at best, repetitive and tedious and tends to drastically
affect code readability.
if you don't have access to a C99 compiler (unlikely).

Really? How many fully conformant C99 compilers are out there? I can
think of about four or five and none that are open source.

But more to the point, Richard has previously indicated quite often,
that he requires his own code to be widely portable across mainframes,
minis, micros etc. I doubt that there exists a C99 compiler that can
satisfy his requirements. Fortunately not everyone needs the same level
of portability though. If you know that your program will only ever be
used on desktops, then you can take C99 a lot more seriously.
As for calculating the required length, I don't think there's a better
or more elegant way than calling snprintf() twice (which I don't think
imposes much overhead, do you?).

It's not a question of overhead at all. Snprintf is simply not an option
to those aiming for strict C90 compliance, like Richard, unless if they
were to roll their own.
 
S

s0suk3

(e-mail address removed) said:


(e-mail address removed) said:
(e-mail address removed) said:
<snip>
int serviceLen = snprintf(NULL, 0, "%d", port);
char service[serviceLen + 1];
snprintf(service, serviceLen, "%d", port);
Faster (because it makes only one call to a string-building routine)
and more portable (because it doesn't depend on either VLAs or
snprintf) is:
char service[(sizeof(int) * CHAR_BIT + 2) / 3 + 2];
sprintf(service, "%d", port);
What does the operation calculate?
The maximum number of decimal digits an int can represent, plus one for
the sign and one for the null terminator.
If it's the max number of digits
that an int can represent:
Right.
wouldn't that allocate more space that might be needed?
It's possible, yes. For example, if CHAR_BIT is 33 (i.e. there are 33
bits in a byte) and sizeof(int) is 5, with no padding bits and one sign
bit, we have 164 value bits (and 1 sign bit), so INT_MAX is a
fifty-digit number (in fact it's
23384026197294446691258957323460528314494920687615), and my expression
(excluding provision for the sign byte and the null byte) yields 166 / 3
= 55, so a massive five bytes are wasted.
Feel free to devise a better algorithm, bearing in mind that you can't
take logs or do anything else that involves runtime evaluation (because
otherwise it won't be a constant integer expression and therefore it
won't be suitable for sizing a C90 array).
Why does it have to be a C90 array?

Because it's convenient to be able to do this with C90 arrays.
You can always use either a VLA,

Maybe you can. I can't, and neither can anyone else who can't risk the
portability issues inherent in using C99 features.

Let's not start another C89/C90/C99 was, as it seems to happen
everyday around here. But for the sake of argument: *what* do you
deploy in (if I may know)? I've always used GNU GCC's C99
implementation... I know, I know, they don't claim full C99
conformance. But that's a fact that's never affected me in any way so
far.
How is that an advantage over a C90 array?

In this particular case it's obvious, isn't it? That you can use
runtime evaluation to calculate the required size.
Hardly anyone has access to a C99 implementation. Microsoft don't do one.
Borland don't do one. GNU don't do one. That's a huge proportion of the C
marketplace right there.


If snprintf isn't there, it's hard to see how calling it is even possible,
let alone desirable. And if it /is/ there, you gain nothing (and may lose
a little) by calling it twice, compared to calling it once and sprintf
once.

Well, by calling

snprintf() twice,
you gain the assurance of allocating the right size without the
danger of overflow or the inconvenient need to make inaccurate
guesses. By calling

snprintf() once,
you gain the assurance of no overflow, but you still might need to
make inaccurate size guesses. And by calling

sprintf() once,
you gain neither one of those :(

Sebastian
 
S

s0suk3

(e-mail address removed) said:
(e-mail address removed) said:
(e-mail address removed) said:
<snip>
int serviceLen = snprintf(NULL, 0, "%d", port);
char service[serviceLen + 1];
snprintf(service, serviceLen, "%d", port);
Faster (because it makes only one call to a string-building routine)
and more portable (because it doesn't depend on either VLAs or
snprintf) is:
char service[(sizeof(int) * CHAR_BIT + 2) / 3 + 2];
sprintf(service, "%d", port);
What does the operation calculate?
The maximum number of decimal digits an int can represent, plus one for
the sign and one for the null terminator.
If it's the max number of digits
that an int can represent:
Right.
wouldn't that allocate more space that might be needed?
It's possible, yes. For example, if CHAR_BIT is 33 (i.e. there are 33
bits in a byte) and sizeof(int) is 5, with no padding bits and one sign
bit, we have 164 value bits (and 1 sign bit), so INT_MAX is a
fifty-digit number (in fact it's
23384026197294446691258957323460528314494920687615), and my expression
(excluding provision for the sign byte and the null byte) yields 166 / 3
= 55, so a massive five bytes are wasted.
Feel free to devise a better algorithm, bearing in mind that you can't
take logs or do anything else that involves runtime evaluation (because
otherwise it won't be a constant integer expression and therefore it
won't be suitable for sizing a C90 array).
Why does it have to be a C90 array?
Because it's convenient to be able to do this with C90 arrays.
Maybe you can. I can't, and neither can anyone else who can't risk the
portability issues inherent in using C99 features.

Let's not start another C89/C90/C99 was,

I meant war...
as it seems to happen
everyday around here. But for the sake of argument: *what* do you
deploy in (if I may know)?

Never mind; Santosh already answered that.

<snip>

Sebastian
 
R

Richard

CBFalconer said:
Use the null device to receive the testing run. Most systems have
such a device available.

Most systems? Oh dear me Chuck. You break your own rules by your own
admission. Off topic. Non portable. "We do not discuss such things here"
is what, I believe, you would tell everyone else.
 
C

CBFalconer

Richard said:
(e-mail address removed) said:
.... snip ...


Hardly anyone has access to a C99 implementation. Microsoft don't
do one. Borland don't do one. GNU don't do one. That's a huge
proportion of the C marketplace right there.

Oh come on now. Gnu has relatively minor failures in C99
compliance. Admittedly it isn't all the way there, but you only
need one compiler.
 
C

CBFalconer

Richard said:
CBFalconer said:

This doesn't answer the question. How does %n improve matters?

It allows routines in the printf group to report the number of
chars emitted. From this you can resolve the size of buffer
needed, and malloc it. Admittedly finding the system null device
is a nuisance, and non-portable. I published, and you snipped, the
standard sections on the %n feature.
 
S

santosh

CBFalconer said:
Use the null device to receive the testing run. Most systems have
such a device available.

I strongly suspect that snprintf itself is more widely available than
a "null device". Thus using a "null device" is almost certainly less
portable than using snprintf.
 

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,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top