function showing date

I

Ike Naar

Barry Schwarz said:
snprintf will return the number of characters that would have been
written if n had been large enough. %24s provides a minimum width.
Adding 1 for the '\n' and 1 for the '\0' means showtime will always
return at least 26.

What is the the purpose of defining a minimum width of field in a format
specifier, if 'snprintf' will write different number of chars?

Considering all the amendments, I fix the code as follows:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define BUFSIZE(b) (sizeof b)

static size_t
showtime(char buf[], const size_t len)
{
time_t ticks;
int nchars;

if ( (ticks = time(NULL)) < 0 ) {
ticks = 0;
}
nchars = snprintf(buf, len, "%25s", ctime(&ticks));
return nchars;
}

int main(void)
{
char buf[26] = "";
size_t n;

n = showtime(buf, sizeof buf);
if ( n >= 0 && n < BUFSIZE(buf)) {

ctime returns the address of a string of length 25. snprintf will add
a '\0' to this. showtime should always return 26. The right operand
of the && operator should always evaluate to false.

snprintf returns the number of characters that would have been
printed if the size of the buffer were unlimited, *excluding* the
final '\0'.
So if the string returned by ctime has length 25,
then snprintf, and hence showtime, return 25 as well.

Style issues:
What's the added value of the BUFSIZE macro?
Why is ``sizeof buf'' used in the showtime call, but ``BUFSIZE(buf)''
in the ``if'' expression that follows it?
n is an unsigned number, so the ``n >= 0'' test always returns true.
 
M

Mark

Ike Naar said:
snprintf returns the number of characters that would have been
printed if the size of the buffer were unlimited, *excluding* the
final '\0'.
So if the string returned by ctime has length 25,
then snprintf, and hence showtime, return 25 as well.

In addition to this, the C99 standard says:
"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 neg ative value if an encoding error occurred. Thus, the
null-terminated output has been completely written if and only if the
returned value is nonnegative and less than n."

So I believe, my intention to compare a result of function with 'sizeof buf'
is correct.
Style issues:
What's the added value of the BUFSIZE macro?
Why is ``sizeof buf'' used in the showtime call, but ``BUFSIZE(buf)''
in the ``if'' expression that follows it?
n is an unsigned number, so the ``n >= 0'' test always returns true.

Changing n's type from size_t to int results in compiler's warning, because
comparisos is done with 'size_t' object:

static int showtime(char buf[], const size_t len)
{
....
}
....
int n;
n = showtime(buf, sizeof buf);
if ( n > 0 && n < sizeof buf) { /* warning: comparison between signed and
unsigned */
....
}
 
I

Ike Naar

Ike Naar said:
n is an unsigned number, so the ``n >= 0'' test always returns true.

Changing n's type from size_t to int results in compiler's warning, because
comparisos is done with 'size_t' object:

static int showtime(char buf[], const size_t len)
{
...
}
...
int n;
n = showtime(buf, sizeof buf);
if ( n > 0 && n < sizeof buf) { /* warning: comparison between signed and
unsigned */
...
}

I was just trying to say that, when n is unsigned, you can simplify
(n >= 0 && n < sizeof buf) to the equivalent (n < sizeof buf) .

Note that if the snprintf call inside showtime()
fails and returns a negative result (typically -1), then you lose
that information when you assign the negative value to an unsigned
variable; the unsigned variable will then have a very large positive
value (typically SIZE_MAX) because of wrap-around.

Here it is probably not a big deal, since a very large n will be
larger than ``sizeof buf'', so the ``if'' condition will be false anyway.
 
B

Barry Schwarz

snprintf will return the number of characters that would have been
written if n had been large enough. %24s provides a minimum width.
Adding 1 for the '\n' and 1 for the '\0' means showtime will always
return at least 26.

What is the the purpose of defining a minimum width of field in a format
specifier, if 'snprintf' will write different number of chars?

Considering all the amendments, I fix the code as follows:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define BUFSIZE(b) (sizeof b)

static size_t
showtime(char buf[], const size_t len)
{
time_t ticks;
int nchars;

if ( (ticks = time(NULL)) < 0 ) {
ticks = 0;
}
nchars = snprintf(buf, len, "%25s", ctime(&ticks));
return nchars;
}

int main(void)
{
char buf[26] = "";
size_t n;

n = showtime(buf, sizeof buf);
if ( n >= 0 && n < BUFSIZE(buf)) {

ctime returns the address of a string of length 25. snprintf will add
a '\0' to this. showtime should always return 26. The right operand
of the && operator should always evaluate to false.

snprintf returns the number of characters that would have been
printed if the size of the buffer were unlimited, *excluding* the
final '\0'.
So if the string returned by ctime has length 25,
then snprintf, and hence showtime, return 25 as well.
Damn, that's two wrong and I'm only 10% through today's download. I
think I'll blame the play my wife dragged me to.
 
M

Mark

Ike Naar said:
I was just trying to say that, when n is unsigned, you can simplify
(n >= 0 && n < sizeof buf) to the equivalent (n < sizeof buf) .

Note that if the snprintf call inside showtime()
fails and returns a negative result (typically -1), then you lose
that information when you assign the negative value to an unsigned
variable; the unsigned variable will then have a very large positive
value (typically SIZE_MAX) because of wrap-around.

Correct, I understood your last post and therefore chanaged return type of
showtime() from size_t to int, so that to catch an error return of
snprintf(). But now GCC spits out a warning on comparison between signed and
unsigned:

int n;

n = showtime(buf, sizeof buf);
if ( n > 0 && n < sizeof buf) {
....

I see only two ways:
1) cast result of (sizeof buf) to int, but casting is generally not
encouraged
2) assign a constant integer variable with a size of buffer and compare to
it

What is the common way to resolve such warnings in cases when above
mentioned solutions are not available by some reasons?
 
I

Ike Naar

int n;
n = showtime(buf, sizeof buf);
if ( n > 0 && n < sizeof buf) {
...

Just curious: why did you change the ``if'' condition from the
I see only two ways:
1) cast result of (sizeof buf) to int, but casting is generally not
encouraged

Variation 1a): cast n to size_t:
if (n >= 0 && (size_t) n < sizeof buf)
2) assign a constant integer variable with a size of buffer and compare to
it

Variation 2a): use a preprocessor macro:
#define SIZE_OF_BUFFER 26
char buf[SIZE_OF_BUFFER];
int n:
if (n >= 0 && n < SIZE_OF_BUFFER)

3) size_t n = showtime(buf, sizeof buf);
if (n < sizeof buf)

As mentioned upthread, the silent conversion from a negative result of
showtime() to a very large positive value for n is relatively harmless
in this particular case.

4) re-work your code; e.g. if all you ever to with the result of
showtime() is print it, you might as well print it inside the
function, and get rid of the buffer, the snprintf call, and the
test that caused the compiler warning:

void showtime(FILE *f)
{
time_t ticks = time(NULL);
if (ticks < 0)
{
ticks = 0;
}
fputs(ctime(&ticks), f);
}
 
M

Mark

Ike Naar said:
Just curious: why did you change the ``if'' condition from the
original (n >= 0 && n < sizeof buf) to (n > 0 && n < sizeof buf) ?
The case n==0 is okay for ``...'' .

That was a typo. And thanks for your valuable comments.

<skip>
 

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,780
Messages
2,569,608
Members
45,251
Latest member
41Ki

Latest Threads

Top