Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #64744 > unrolled thread

sprintf and the trailing null

Started by"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
First post2015-07-06 06:16 -0700
Last post2015-07-07 21:48 -0500
Articles 20 on this page of 70 — 20 participants

Back to article view | Back to comp.lang.c


Contents

  sprintf and the trailing null "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-06 06:16 -0700
    Re: sprintf and the trailing null John McCue <jmccue@jmcnet1.bstnma.east.verizon.net> - 2015-07-06 13:30 +0000
      Re: sprintf and the trailing null "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-06 06:37 -0700
        Re: sprintf and the trailing null Reinhardt Behm <rbehm@hushmail.com> - 2015-07-06 21:58 +0800
          Re: sprintf and the trailing null "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-06 07:12 -0700
            Re: sprintf and the trailing null Reinhardt Behm <rbehm@hushmail.com> - 2015-07-06 22:34 +0800
              Re: sprintf and the trailing null "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-06 08:44 -0700
            Re: sprintf and the trailing null Bartc <bc@freeuk.com> - 2015-07-06 15:46 +0100
              Re: sprintf and the trailing null Keith Thompson <kst-u@mib.org> - 2015-07-06 08:06 -0700
                Re: sprintf and the trailing null Bartc <bc@freeuk.com> - 2015-07-06 17:42 +0100
                  Re: sprintf and the trailing null "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-06 09:48 -0700
                  Re: sprintf and the trailing null Bartc <bc@freeuk.com> - 2015-07-06 18:07 +0100
                    Re: sprintf and the trailing null Martin Shobe <martin.shobe@yahoo.com> - 2015-07-06 12:40 -0500
                  Re: sprintf and the trailing null Keith Thompson <kst-u@mib.org> - 2015-07-06 10:46 -0700
                    Re: sprintf and the trailing null Bartc <bc@freeuk.com> - 2015-07-06 18:58 +0100
            Re: sprintf and the trailing null Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-07-06 16:38 +0100
              Re: sprintf and the trailing null Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-07-06 23:44 +0100
                Re: sprintf and the trailing null "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-06 15:48 -0700
                Re: sprintf and the trailing null Phil Carmody <pc+usenet@asdf.org> - 2015-07-08 20:09 +0300
                  Re: sprintf and the trailing null "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-08 10:11 -0700
                    Re: sprintf and the trailing null Bartc <bc@freeuk.com> - 2015-07-08 19:01 +0100
                      Re: sprintf and the trailing null David Kleinecke <dkleinecke@gmail.com> - 2015-07-09 09:02 -0700
                        Re: sprintf and the trailing null Richard Heathfield <rjh@cpax.org.uk> - 2015-07-09 17:07 +0100
                          Re: sprintf and the trailing null Phil Carmody <pc+usenet@asdf.org> - 2015-07-10 17:06 +0300
                        Re: sprintf and the trailing null glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-07-09 17:42 +0000
                      Re: sprintf and the trailing null Phil Carmody <pc+usenet@asdf.org> - 2015-07-10 13:33 +0300
                        Re: sprintf and the trailing null Bartc <bc@freeuk.com> - 2015-07-10 12:09 +0100
                          Re: sprintf and the trailing null Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-07-10 04:51 -0700
                            Re: sprintf and the trailing null Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-07-10 17:24 +0100
                          Re: sprintf and the trailing null Keith Thompson <kst-u@mib.org> - 2015-07-10 08:33 -0700
                  Re: sprintf and the trailing null Tim Rentsch <txr@alumni.caltech.edu> - 2015-07-11 04:58 -0700
        Re: sprintf and the trailing null jt@toerring.de (Jens Thoms Toerring) - 2015-07-06 14:15 +0000
          Re: sprintf and the trailing null "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-06 07:20 -0700
            Re: sprintf and the trailing null raltbos@xs4all.nl (Richard Bos) - 2015-07-06 19:54 +0000
              Re: sprintf and the trailing null "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-06 13:31 -0700
                Re: sprintf and the trailing null Richard Heathfield <rjh@cpax.org.uk> - 2015-07-06 21:52 +0100
                Re: sprintf and the trailing null raltbos@xs4all.nl (Richard Bos) - 2015-07-06 22:52 +0000
                  Re: sprintf and the trailing null Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-07-07 01:04 +0100
                  Re: sprintf and the trailing null Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-07-06 19:13 -0700
                    Re: sprintf and the trailing null Reinhardt Behm <rbehm@hushmail.com> - 2015-07-07 12:45 +0800
                      Re: sprintf and the trailing null Rosario19 <Ros@invalid.invalid> - 2015-07-07 10:15 +0200
                    Re: sprintf and the trailing null Bartc <bc@freeuk.com> - 2015-07-07 10:31 +0100
                      Re: sprintf and the trailing null Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-07-07 02:51 -0700
                        Re: sprintf and the trailing null Bartc <bc@freeuk.com> - 2015-07-07 12:10 +0100
                          Re: sprintf and the trailing null Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-07-07 05:08 -0700
                            Re: sprintf and the trailing null Bartc <bc@freeuk.com> - 2015-07-07 13:52 +0100
                              Re: sprintf and the trailing null Phil Carmody <pc+usenet@asdf.org> - 2015-07-08 20:20 +0300
                                Re: sprintf and the trailing null Bartc <bc@freeuk.com> - 2015-07-08 18:51 +0100
                                Re: sprintf and the trailing null raltbos@xs4all.nl (Richard Bos) - 2015-07-09 10:27 +0000
                            Re: sprintf and the trailing null Tim Rentsch <txr@alumni.caltech.edu> - 2015-07-10 19:03 -0700
                Re: sprintf and the trailing null gordonb.7tw58@burditt.org (Gordon Burditt) - 2015-07-07 15:40 -0500
                  Re: sprintf and the trailing null "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-07 15:14 -0700
          Re: sprintf and the trailing null "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-06 07:27 -0700
            Re: sprintf and the trailing null jt@toerring.de (Jens Thoms Toerring) - 2015-07-06 16:46 +0000
          Re: sprintf and the trailing null Keith Thompson <kst-u@mib.org> - 2015-07-06 07:56 -0700
    Re: sprintf and the trailing null Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2015-07-06 09:32 -0600
    Re: sprintf and the trailing null Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-07-06 08:37 -0700
      Re: sprintf and the trailing null Keith Thompson <kst-u@mib.org> - 2015-07-06 08:54 -0700
    Re: sprintf and the trailing null "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-06 08:53 -0700
      Re: sprintf and the trailing null "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-06 09:00 -0700
      Re: sprintf and the trailing null Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-07-06 17:14 +0100
        Re: sprintf and the trailing null "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-06 09:24 -0700
          Re: sprintf and the trailing null "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-06 09:31 -0700
    Re: sprintf and the trailing null Sjouke Burry <burrynulnulfour@ppllaanneett.nnll> - 2015-07-07 01:43 +0200
      Re: sprintf and the trailing null "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-06 17:09 -0700
        Re: sprintf and the trailing null Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2015-07-06 21:08 -0600
          Re: sprintf and the trailing null "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-06 21:29 -0700
          Re: sprintf and the trailing null Phil Carmody <pc+usenet@asdf.org> - 2015-07-08 20:24 +0300
            Re: sprintf and the trailing null "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-08 10:44 -0700
    Re: sprintf and the trailing null Les Cargill <lcargill99@comcast.com> - 2015-07-07 21:48 -0500

Page 1 of 4  [1] 2 3 4  Next page →


#64744 — sprintf and the trailing null

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2015-07-06 06:16 -0700
Subjectsprintf and the trailing null
Message-ID<be51c03d-a8d6-4c66-b490-85466818284d@googlegroups.com>
Two questions:

  (1) Is there a version of sprintf() without a trailing NULL?
  (2) Why does sprintf() automatically insert a trailing NULL?

TYIA!

Best regards,
Rick C. Hodgin

[toc] | [next] | [standalone]


#64745

FromJohn McCue <jmccue@jmcnet1.bstnma.east.verizon.net>
Date2015-07-06 13:30 +0000
Message-ID<mndvt7$299$1@dont-email.me>
In reply to#64744
Rick C. Hodgin <rick.c.hodgin@gmail.com> wrote:
> Two questions:
> 
>  (1) Is there a version of sprintf() without a trailing NULL?

I have not seen any, but what are you trying to
accomplish ?

>  (2) Why does sprintf() automatically insert a trailing NULL?

You can see why if you replace the 'trailing NULL'
with another character and print out the string.

> 
> TYIA!
> 
> Best regards,
> Rick C. Hodgin

John

[toc] | [prev] | [next] | [standalone]


#64746

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2015-07-06 06:37 -0700
Message-ID<4218c1d7-073c-48a4-8485-687a794848d1@googlegroups.com>
In reply to#64745
On Monday, July 6, 2015 at 9:31:49 AM UTC-4, John McCue wrote:
> Rick C. Hodgin <rick.c.hodgin@gmail.com> wrote:
> > Two questions:
> >  (1) Is there a version of sprintf() without a trailing NULL?
> I have not seen any, but what are you trying to accomplish ?

One example:

    char buffer[8];
    sprintf(buffer, "%04u%02%02u", year, month, day);

> >  (2) Why does sprintf() automatically insert a trailing NULL?
> 
> You can see why if you replace the 'trailing NULL' with another
> character and print out the string.

Why not options:

    sprintf0(buffer, "%04u", value);    // NULL-terminated form
    sprintf(buffer, "%04u\0", value);   // Manually terminated (if needed)

Or at this point in support of legacy systems, a new function:
    rawprintf(buffer, "%04u\0", value); // No NULL-termination by default

Best regards,
Rick C. Hodgin

[toc] | [prev] | [next] | [standalone]


#64748

FromReinhardt Behm <rbehm@hushmail.com>
Date2015-07-06 21:58 +0800
Message-ID<mne1fl$dm7$1@dont-email.me>
In reply to#64746
Rick C. Hodgin wrote:

> On Monday, July 6, 2015 at 9:31:49 AM UTC-4, John McCue wrote:
>> Rick C. Hodgin <rick.c.hodgin@gmail.com> wrote:
>> > Two questions:
>> >  (1) Is there a version of sprintf() without a trailing NULL?
>> I have not seen any, but what are you trying to accomplish ?
> 
> One example:
> 
>     char buffer[8];
>     sprintf(buffer, "%04u%02%02u", year, month, day);
> 
>> >  (2) Why does sprintf() automatically insert a trailing NULL?
>> 
>> You can see why if you replace the 'trailing NULL' with another
>> character and print out the string.
> 
> Why not options:
> 
>     sprintf0(buffer, "%04u", value);    // NULL-terminated form
>     sprintf(buffer, "%04u\0", value);   // Manually terminated (if needed)
> 
> Or at this point in support of legacy systems, a new function:
>     rawprintf(buffer, "%04u\0", value); // No NULL-termination by default

How does this function distinguish between these two format strings?

char *fmt1[] = { '%', '0', '4', 'u', '\0' } 
which is the same as writing "%04u"
and
char *fmt2[] = { '%', '0', '4', 'u', '\0', '\0' }
which is the same as writing "%04u\0"

For the rare case you can always write your above example as
     char buffer[8];
     char buffer1[sizeof(buffer) + 1];
     sprintf(buffer1, "%04u%02%02u", year, month, day);
     strncpy(buffer, buffer1, sizeof(buffer));


-- 
Reinhardt

[toc] | [prev] | [next] | [standalone]


#64750

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2015-07-06 07:12 -0700
Message-ID<8ee8235d-f52a-4e2c-94b5-11d7b86cbc60@googlegroups.com>
In reply to#64748
On Monday, July 6, 2015 at 9:58:43 AM UTC-4, Reinhardt Behm wrote:
> Rick C. Hodgin wrote:
> 
> > On Monday, July 6, 2015 at 9:31:49 AM UTC-4, John McCue wrote:
> >> Rick C. Hodgin <rick.c.hodgin@gmail.com> wrote:
> >> > Two questions:
> >> >  (1) Is there a version of sprintf() without a trailing NULL?
> >> I have not seen any, but what are you trying to accomplish ?
> > 
> > One example:
> > 
> >     char buffer[8];
> >     sprintf(buffer, "%04u%02%02u", year, month, day);
> > 
> >> >  (2) Why does sprintf() automatically insert a trailing NULL?
> >> 
> >> You can see why if you replace the 'trailing NULL' with another
> >> character and print out the string.
> > 
> > Why not options:
> > 
> >     sprintf0(buffer, "%04u", value);    // NULL-terminated form
> >     sprintf(buffer, "%04u\0", value);   // Manually terminated (if needed)
> > 
> > Or at this point in support of legacy systems, a new function:
> >     rawprintf(buffer, "%04u\0", value); // No NULL-termination by default
> 
> How does this function distinguish between these two format strings?
> 
> char *fmt1[] = { '%', '0', '4', 'u', '\0' } 
> which is the same as writing "%04u"
> and
> char *fmt2[] = { '%', '0', '4', 'u', '\0', '\0' }
> which is the same as writing "%04u\0"

It's not the same. The '\0' is interpreted by the compiler as a
NULL.  In order to have the sam, you'd need:

    char *fmt1[] = { '%', '0', '4', 'u', '\', '0', '\0' } 

...physically embedding the \ and 0 as separate characters, then
the trailing null.

> For the rare case you can always write your above example as
>      char buffer[8];
>      char buffer1[sizeof(buffer) + 1];
>      sprintf(buffer1, "%04u%02%02u", year, month, day);
>      strncpy(buffer, buffer1, sizeof(buffer));

Yes.  I'm thinking this double-processing could be avoided with
rawprintf().  Isn't C all about speed?  I mean even the type for
int is supposed to be fast.  Why not a common operation like
preparing an output string for disk, display, network traffic,
or future processing?

Best regards,
Rick C. Hodgin

[toc] | [prev] | [next] | [standalone]


#64755

FromReinhardt Behm <rbehm@hushmail.com>
Date2015-07-06 22:34 +0800
Message-ID<mne3ip$n5k$1@dont-email.me>
In reply to#64750
Rick C. Hodgin wrote:

> On Monday, July 6, 2015 at 9:58:43 AM UTC-4, Reinhardt Behm wrote:
>> Rick C. Hodgin wrote:
>> 
>> > On Monday, July 6, 2015 at 9:31:49 AM UTC-4, John McCue wrote:
>> >> Rick C. Hodgin <rick.c.hodgin@gmail.com> wrote:
>> >> > Two questions:
>> >> >  (1) Is there a version of sprintf() without a trailing NULL?
>> >> I have not seen any, but what are you trying to accomplish ?
>> > 
>> > One example:
>> > 
>> >     char buffer[8];
>> >     sprintf(buffer, "%04u%02%02u", year, month, day);
>> > 
>> >> >  (2) Why does sprintf() automatically insert a trailing NULL?
>> >> 
>> >> You can see why if you replace the 'trailing NULL' with another
>> >> character and print out the string.
>> > 
>> > Why not options:
>> > 
>> >     sprintf0(buffer, "%04u", value);    // NULL-terminated form
>> >     sprintf(buffer, "%04u\0", value);   // Manually terminated (if
>> >     needed)
>> > 
>> > Or at this point in support of legacy systems, a new function:
>> >     rawprintf(buffer, "%04u\0", value); // No NULL-termination by
>> >     default
>> 
>> How does this function distinguish between these two format strings?
>> 
>> char *fmt1[] = { '%', '0', '4', 'u', '\0' }
>> which is the same as writing "%04u"
>> and
>> char *fmt2[] = { '%', '0', '4', 'u', '\0', '\0' }
>> which is the same as writing "%04u\0"
> 
> It's not the same. The '\0' is interpreted by the compiler as a
> NULL. 
When writing "%04u\0" the compiler interprets the \0 as a NUL character and 
appends one as the string delimiter.

> In order to have the sam, you'd need:
> 
>     char *fmt1[] = { '%', '0', '4', 'u', '\', '0', '\0' }
For that you would have to write "%04u\\0".

But it is not about how you write it. It about how the function could 
interpret your format string. If it interprets it as a normal C null-
terminated string the second NUL-character will not be seen, because the 
first you explicitly put in there will be the delimiter.
In this sense the two format strings are equivalent from the functions point 
of view. 

If you want it to be interpreted otherwise, you must tell the function the 
length of the string. This would be incompatible with all C conventions.

> 
> ...physically embedding the \ and 0 as separate characters, then
> the trailing null.
> 
>> For the rare case you can always write your above example as
>>      char buffer[8];
>>      char buffer1[sizeof(buffer) + 1];
>>      sprintf(buffer1, "%04u%02%02u", year, month, day);
>>      strncpy(buffer, buffer1, sizeof(buffer));
> 
> Yes.  I'm thinking this double-processing could be avoided with
> rawprintf().  Isn't C all about speed?  I mean even the type for
> int is supposed to be fast.  Why not a common operation like
> preparing an output string for disk, display, network traffic,
> or future processing?

Is this such a common requirement? When you create strings you usually want 
to handle them with normal string functions. These will all not work with 
you non-delimited "strings".
So you would have to use these always with additional length information. 
That's also easy when using the normal s(n)printf with a destination buffer 
one longer than needed and passing the appropriate length argument 
(bufferlen -1).

-- 
Reinhardt

[toc] | [prev] | [next] | [standalone]


#64766

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2015-07-06 08:44 -0700
Message-ID<ee5d4835-4a47-4b13-aaef-91e778e2ba0a@googlegroups.com>
In reply to#64755
On Monday, July 6, 2015 at 10:34:31 AM UTC-4, Reinhardt Behm wrote:
> Rick C. Hodgin wrote:
> 
> > On Monday, July 6, 2015 at 9:58:43 AM UTC-4, Reinhardt Behm wrote:
> >> Rick C. Hodgin wrote:
> >> 
> >> > On Monday, July 6, 2015 at 9:31:49 AM UTC-4, John McCue wrote:
> >> >> Rick C. Hodgin <rick.c.hodgin@gmail.com> wrote:
> >> >> > Two questions:
> >> >> >  (1) Is there a version of sprintf() without a trailing NULL?
> >> >> I have not seen any, but what are you trying to accomplish ?
> >> > 
> >> > One example:
> >> > 
> >> >     char buffer[8];
> >> >     sprintf(buffer, "%04u%02%02u", year, month, day);
> >> > 
> >> >> >  (2) Why does sprintf() automatically insert a trailing NULL?
> >> >> 
> >> >> You can see why if you replace the 'trailing NULL' with another
> >> >> character and print out the string.
> >> > 
> >> > Why not options:
> >> > 
> >> >     sprintf0(buffer, "%04u", value);    // NULL-terminated form
> >> >     sprintf(buffer, "%04u\0", value);   // Manually terminated (if
> >> >     needed)
> >> > 
> >> > Or at this point in support of legacy systems, a new function:
> >> >     rawprintf(buffer, "%04u\0", value); // No NULL-termination by
> >> >     default
> >> 
> >> How does this function distinguish between these two format strings?
> >> 
> >> char *fmt1[] = { '%', '0', '4', 'u', '\0' }
> >> which is the same as writing "%04u"
> >> and
> >> char *fmt2[] = { '%', '0', '4', 'u', '\0', '\0' }
> >> which is the same as writing "%04u\0"
> > 
> > It's not the same. The '\0' is interpreted by the compiler as a
> > NULL. 
> When writing "%04u\0" the compiler interprets the \0 as a NUL character and 
> appends one as the string delimiter.
> 
> > In order to have the sam, you'd need:
> > 
> >     char *fmt1[] = { '%', '0', '4', 'u', '\', '0', '\0' }
> For that you would have to write "%04u\\0".
> 
> But it is not about how you write it. It about how the function could 
> interpret your format string. If it interprets it as a normal C null-
> terminated string the second NUL-character will not be seen, because the 
> first you explicitly put in there will be the delimiter.
> In this sense the two format strings are equivalent from the functions point 
> of view. 
> 
> If you want it to be interpreted otherwise, you must tell the function the 
> length of the string. This would be incompatible with all C conventions.

Quite correct.  My mistake.

> > ...physically embedding the \ and 0 as separate characters, then
> > the trailing null.
> > 
> >> For the rare case you can always write your above example as
> >>      char buffer[8];
> >>      char buffer1[sizeof(buffer) + 1];
> >>      sprintf(buffer1, "%04u%02%02u", year, month, day);
> >>      strncpy(buffer, buffer1, sizeof(buffer));
> > 
> > Yes.  I'm thinking this double-processing could be avoided with
> > rawprintf().  Isn't C all about speed?  I mean even the type for
> > int is supposed to be fast.  Why not a common operation like
> > preparing an output string for disk, display, network traffic,
> > or future processing?
> 
> Is this such a common requirement? When you create strings you usually want 
> to handle them with normal string functions. These will all not work with 
> you non-delimited "strings".
> So you would have to use these always with additional length information. 
> That's also easy when using the normal s(n)printf with a destination buffer 
> one longer than needed and passing the appropriate length argument 
> (bufferlen -1).

Yes, it's a common requirement.  I use sprintf() to build things
from variable data for various purposes.  Having the trailing null
is useful at times, but other times it is not useful, and there
doesn't seem to be a way to bypass it without doing double the
memory work.

Best regards,
Rick C. Hodgin

[toc] | [prev] | [next] | [standalone]


#64756

FromBartc <bc@freeuk.com>
Date2015-07-06 15:46 +0100
Message-ID<mne4af$q93$1@dont-email.me>
In reply to#64750
On 06/07/2015 15:12, Rick C. Hodgin wrote:
> On Monday, July 6, 2015 at 9:58:43 AM UTC-4, Reinhardt Behm wrote:

>> For the rare case you can always write your above example as
>>       char buffer[8];
>>       char buffer1[sizeof(buffer) + 1];
>>       sprintf(buffer1, "%04u%02%02u", year, month, day);
>>       strncpy(buffer, buffer1, sizeof(buffer));
>
> Yes.  I'm thinking this double-processing could be avoided with
> rawprintf().  Isn't C all about speed?

Having a duplicate set of printf functions that don't append nul aren't 
going to be that useful.

Usually, you will not know that size of the resulting string, which 
means providing a buffer with spare capacity. One of those spare bytes 
will have a zero inserted; just ignore it (or set it back to a space or 
whatever the original was).

If you do know the length of the result, as in the above example, then 
snprintf() will not append the nul, if the buffer provided is exactly 
the write size.

I don't think that leaves many other examples where such a duplicate set 
of functions as you propose would be worthwhile adding.

-- 
Bartc

[toc] | [prev] | [next] | [standalone]


#64760

FromKeith Thompson <kst-u@mib.org>
Date2015-07-06 08:06 -0700
Message-ID<lnvbdxuxz2.fsf@kst-u.example.com>
In reply to#64756
Bartc <bc@freeuk.com> writes:
[...]
> If you do know the length of the result, as in the above example, then 
> snprintf() will not append the nul, if the buffer provided is exactly 
> the write size.

That's incorrect; snprintf always writes a terminating null
character to the target array (unless n==0 and it doesn't write
anything at all).  It will truncate the output if necesesary to leave
room for the '\0'.  N1570 7.21.6.5p2:

    The snprintf function is equivalent to fprintf, except that
    the output is written into an array (specified by argument s)
    rather than to a stream. If n is zero, nothing is written, and
    s may be a null pointer. Otherwise, output characters beyond
    the n-1st are discarded rather than being written to the array,
    and a null character is written at the end of the characters
    actually written into the array. If copying takes place between
    objects that overlap, the behavior is undefined.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#64775

FromBartc <bc@freeuk.com>
Date2015-07-06 17:42 +0100
Message-ID<mneb3m$n6e$1@dont-email.me>
In reply to#64760
On 06/07/2015 16:06, Keith Thompson wrote:
> Bartc <bc@freeuk.com> writes:
> [...]
>> If you do know the length of the result, as in the above example, then
>> snprintf() will not append the nul, if the buffer provided is exactly
>> the write size.
>
> That's incorrect; snprintf always writes a terminating null
> character to the target array (unless n==0 and it doesn't write
> anything at all).  It will truncate the output if necesesary to leave
> room for the '\0'.  N1570 7.21.6.5p2:
>
>      The snprintf function is equivalent to fprintf, except that
>      the output is written into an array (specified by argument s)
>      rather than to a stream. If n is zero, nothing is written, and
>      s may be a null pointer. Otherwise, output characters beyond
>      the n-1st are discarded rather than being written to the array,
>      and a null character is written at the end of the characters
>      actually written into the array. If copying takes place between
>      objects that overlap, the behavior is undefined.
>

MS' doc say otherwise:
-----------------------
Let len be the length of the formatted data string, not including the 
terminating null. len and count are in bytes for _snprintf, wide 
characters for _snwprintf.

If len < count, len characters are stored in buffer, a null-terminator 
is appended, and len is returned.

If len = count, len characters are stored in buffer, no null-terminator 
is appended, and len is returned.

If len > count, count characters are stored in buffer, no 
null-terminator is appended, and a negative value is returned.
-----------------------

But most C compilers behave as you suggest. I was hoping to be able to 
run MSVC in the form of CL.EXE (/this/ is the sort of reason I wanted it 
around, but it's not worth 6-11GB of disk space!), but it failed trying 
to link in snprintf(). And I've no idea how to fix it.

I think Rick uses MSVC and that might have been a (non-portable) 
solution if it behaved as its docs say.

However, TCC (Tiny C Compiler) appears to behave like MS says it does. 
The following program prints 49 50 0 99... on most compilers, but 49 50 
51 99 ... with TCC:

#include <stdio.h>

int main(void) {
char str[]={99,99,99,99,99,99,99,99};
int i;

snprintf(str,3,"%3d",12345);

for (i=0; i<sizeof(str); ++i)
	printf("%d ",str[i]);
}

-- 
Bartc

[toc] | [prev] | [next] | [standalone]


#64777

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2015-07-06 09:48 -0700
Message-ID<0bebeaa3-456f-4dff-a410-597dee01e788@googlegroups.com>
In reply to#64775
On Monday, July 6, 2015 at 12:42:59 PM UTC-4, Bart wrote:
> I think Rick uses MSVC and that might have been a (non-portable) 
> solution if it behaved as its docs say.

I use Visual Studio and MSVC for 99.5% of development, and then MSVC
and GCC for testing and final debugging on shipped products for most
everything these days, making sure my code compiles in both (at least
once every several days that is, as the only development I do outside
of Visual Studio and MSVC is when I'm fixing up code that doesn't
work in GCC).

Best regards,
Rick C. Hodgin

[toc] | [prev] | [next] | [standalone]


#64780

FromBartc <bc@freeuk.com>
Date2015-07-06 18:07 +0100
Message-ID<mnecik$tit$1@dont-email.me>
In reply to#64775
On 06/07/2015 17:42, Bartc wrote:

> If len = count, len characters are stored in buffer, no null-terminator
> is appended, and len is returned.
>
> If len > count, count characters are stored in buffer, no
> null-terminator is appended, and a negative value is returned.
> -----------------------
>
> But most C compilers behave as you suggest. I was hoping to be able to
> run MSVC in the form of CL.EXE (/this/ is the sort of reason I wanted it
> around, but it's not worth 6-11GB of disk space!), but it failed trying
> to link in snprintf(). And I've no idea how to fix it.

The 'fix' seems to be to call _snprintf() instead (I thought the "_" 
prefix was something prepended to all global names, something to do with 
how linking works.)

Anyway, MSVC doesn't add the terminator in the above circumstances, but 
it also seems this is not standard behaviour and that it might have 
changed in the most recent version!

-- 
Bartc

[toc] | [prev] | [next] | [standalone]


#64781

FromMartin Shobe <martin.shobe@yahoo.com>
Date2015-07-06 12:40 -0500
Message-ID<mneef5$62e$1@dont-email.me>
In reply to#64780
On 7/6/2015 12:07 PM, Bartc wrote:
> On 06/07/2015 17:42, Bartc wrote:
>
>> If len = count, len characters are stored in buffer, no null-terminator
>> is appended, and len is returned.
>>
>> If len > count, count characters are stored in buffer, no
>> null-terminator is appended, and a negative value is returned.
>> -----------------------
>>
>> But most C compilers behave as you suggest. I was hoping to be able to
>> run MSVC in the form of CL.EXE (/this/ is the sort of reason I wanted it
>> around, but it's not worth 6-11GB of disk space!), but it failed trying
>> to link in snprintf(). And I've no idea how to fix it.
>
> The 'fix' seems to be to call _snprintf() instead (I thought the "_"
> prefix was something prepended to all global names, something to do with
> how linking works.)

Microsoft does do that to indicate the calling convention for 32-bit 
programs, however, the rules for that apply to _snprintf() as well, so, 
if I remember the rules correctly, the identifier _snprintf maps to the 
symbol __snprintf (two leading underscores).

> Anyway, MSVC doesn't add the terminator in the above circumstances, but
> it also seems this is not standard behaviour and that it might have
> changed in the most recent version!

It's not standard behavior (Microsoft doesn't claim it conforms either), 
and I don't think it has changed recently.

Martin Shobe

[toc] | [prev] | [next] | [standalone]


#64782

FromKeith Thompson <kst-u@mib.org>
Date2015-07-06 10:46 -0700
Message-ID<lnmvz9uqk3.fsf@kst-u.example.com>
In reply to#64775
Bartc <bc@freeuk.com> writes:
> On 06/07/2015 16:06, Keith Thompson wrote:
>> Bartc <bc@freeuk.com> writes:
>> [...]
>>> If you do know the length of the result, as in the above example, then
>>> snprintf() will not append the nul, if the buffer provided is exactly
>>> the write size.
>>
>> That's incorrect; snprintf always writes a terminating null
>> character to the target array (unless n==0 and it doesn't write
>> anything at all).  It will truncate the output if necesesary to leave
>> room for the '\0'.  N1570 7.21.6.5p2:
>>
>>      The snprintf function is equivalent to fprintf, except that
>>      the output is written into an array (specified by argument s)
>>      rather than to a stream. If n is zero, nothing is written, and
>>      s may be a null pointer. Otherwise, output characters beyond
>>      the n-1st are discarded rather than being written to the array,
>>      and a null character is written at the end of the characters
>>      actually written into the array. If copying takes place between
>>      objects that overlap, the behavior is undefined.
>>
>
> MS' doc say otherwise:
> -----------------------
> Let len be the length of the formatted data string, not including the 
> terminating null. len and count are in bytes for _snprintf, wide 
> characters for _snwprintf.

The document you're quoting is for something called _snprintf, which is
a distinct function, with a different name, from the standard snprintf.

(snprintf was added to C by the 1999 standard.  I think Microsoft
invented its own non-standard version before that.)

[...]

> But most C compilers behave as you suggest. I was hoping to be able to 
> run MSVC in the form of CL.EXE (/this/ is the sort of reason I wanted it 
> around, but it's not worth 6-11GB of disk space!), but it failed trying 
> to link in snprintf(). And I've no idea how to fix it.

*All* C implementations (for C99 or later) behave like that.  Any that
don't are not C implementations.

> I think Rick uses MSVC and that might have been a (non-portable) 
> solution if it behaved as its docs say.
>
> However, TCC (Tiny C Compiler) appears to behave like MS says it does. 
> The following program prints 49 50 0 99... on most compilers, but 49 50 
> 51 99 ... with TCC:
>
> #include <stdio.h>
>
> int main(void) {
> char str[]={99,99,99,99,99,99,99,99};
> int i;
>
> snprintf(str,3,"%3d",12345);
>
> for (i=0; i<sizeof(str); ++i)
> 	printf("%d ",str[i]);
> }

If so, then tcc is non-conforming.  But I just tried it with tcc version
0.9.25 on Linux Mint, and it behaves correctly.

As far as I can tell, tcc uses the system's C library.  snprintf is
implemented by the library, not by the compiler.  It may be that tcc is
using a non-conforming C library on your system.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#64783

FromBartc <bc@freeuk.com>
Date2015-07-06 18:58 +0100
Message-ID<mnefib$a9s$1@dont-email.me>
In reply to#64782
On 06/07/2015 18:46, Keith Thompson wrote:
> Bartc <bc@freeuk.com> writes:

>> However, TCC (Tiny C Compiler) appears to behave like MS says it does.
>> The following program prints 49 50 0 99... on most compilers, but 49 50
>> 51 99 ... with TCC:
>>
>> #include <stdio.h>
>>
>> int main(void) {
>> char str[]={99,99,99,99,99,99,99,99};
>> int i;
>>
>> snprintf(str,3,"%3d",12345);
>>
>> for (i=0; i<sizeof(str); ++i)
>> 	printf("%d ",str[i]);
>> }
>
> If so, then tcc is non-conforming.  But I just tried it with tcc version
> 0.9.25 on Linux Mint, and it behaves correctly.
>
> As far as I can tell, tcc uses the system's C library.  snprintf is
> implemented by the library, not by the compiler.  It may be that tcc is
> using a non-conforming C library on your system.

I was using 0.9.26. But on Linux, it behaves like other compilers.

So it's more than likely that it's using MS' C runtime library, but 
without the need to call _snprintf instead. I suppose that's one way of 
keeping it tiny.

-- 
Bartc

[toc] | [prev] | [next] | [standalone]


#64765

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2015-07-06 16:38 +0100
Message-ID<87a8v9uwi8.fsf@bsb.me.uk>
In reply to#64750
"Rick C. Hodgin" <rick.c.hodgin@gmail.com> writes:

> On Monday, July 6, 2015 at 9:58:43 AM UTC-4, Reinhardt Behm wrote:
>> Rick C. Hodgin wrote:
>> 
>> > On Monday, July 6, 2015 at 9:31:49 AM UTC-4, John McCue wrote:
>> >> Rick C. Hodgin <rick.c.hodgin@gmail.com> wrote:
>> >> > Two questions:
>> >> >  (1) Is there a version of sprintf() without a trailing NULL?
>> >> I have not seen any, but what are you trying to accomplish ?
>> > 
>> > One example:
>> > 
>> >     char buffer[8];
>> >     sprintf(buffer, "%04u%02%02u", year, month, day);
>> > 
>> >> >  (2) Why does sprintf() automatically insert a trailing NULL?
>> >> 
>> >> You can see why if you replace the 'trailing NULL' with another
>> >> character and print out the string.
>> > 
>> > Why not options:
>> > 
>> >     sprintf0(buffer, "%04u", value);    // NULL-terminated form
>> >     sprintf(buffer, "%04u\0", value);   // Manually terminated (if needed)
>> > 
>> > Or at this point in support of legacy systems, a new function:
>> >     rawprintf(buffer, "%04u\0", value); // No NULL-termination by default
>> 
>> How does this function distinguish between these two format strings?
>> 
>> char *fmt1[] = { '%', '0', '4', 'u', '\0' } 
>> which is the same as writing "%04u"
>> and
>> char *fmt2[] = { '%', '0', '4', 'u', '\0', '\0' }
>> which is the same as writing "%04u\0"
>
> It's not the same.

You are right it isn't but not for the reason you state.  Reinhardt has
a typo -- there's an unintended * in the type.

What you wrote ("%04u\0") denotes (char)[]{'%', '0', '4', 'u', 0, 0}.
There's not way for sprintf to tell the difference between the null you
put there explicitly and the one that ends a string literal.

> The '\0' is interpreted by the compiler as a NULL.

'\0' is the same as 0 and denotes character called null.

> In order to have the sam, you'd need:
>
>     char *fmt1[] = { '%', '0', '4', 'u', '\', '0', '\0' } 
>
> ...physically embedding the \ and 0 as separate characters, then
> the trailing null.

That's not even valid C (even when the pointer is removed from the
declaration).  You might have meant '\\' in the initialiser, but that's
just as bad as adding a null character.

sprintf already has the right mechanism -- the % syntax.  You could
propose a new conversion specifier which, like %%, denotes a single
character -- a null.  It would mainly be useful in your memprintf
function:

  memprintf(buffer, "%4u%!", year); // terminated -- min 5 bytes written
  memprintf(buffer, "%4u%!", year); // min 4 bytes written, no null

>> For the rare case you can always write your above example as
>>      char buffer[8];
>>      char buffer1[sizeof(buffer) + 1];
>>      sprintf(buffer1, "%04u%02%02u", year, month, day);
>>      strncpy(buffer, buffer1, sizeof(buffer));
>
> Yes.  I'm thinking this double-processing could be avoided with
> rawprintf().

You can avoid the double copy (in many cases) like this:

     union {
          char unterminated[8];
          char string[8 + 1];
     } buffer;
     sprintf(buffer.string, "%04u%02u%02u", year, month, day);

and then use buffer.unterminated with its helpfully worrying name.
Alternatively, you could write:

     char buffer[8];
     snprintf(buffer, sizeof buffer, "%04u%02u%02u", year, month, day);
     buffer[sizeof buffer - 1] = '0' + day % 10;

which is not very nice, but it's safer all round because you can't
overflow the buffer due to bad values in the printed variables.

<snip>
-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#64807

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2015-07-06 23:44 +0100
Message-ID<87k2ucucrk.fsf@bsb.me.uk>
In reply to#64765
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
<snip>
>>> >> Rick C. Hodgin <rick.c.hodgin@gmail.com> wrote:
>>> >> >  (1) Is there a version of sprintf() without a trailing NULL?
<snip>
> sprintf already has the right mechanism -- the % syntax.  You could
> propose a new conversion specifier which, like %%, denotes a single
> character -- a null.  It would mainly be useful in your memprintf
> function:
>
>   memprintf(buffer, "%4u%!", year); // terminated -- min 5 bytes written
>   memprintf(buffer, "%4u%!", year); // min 4 bytes written, no null

A thought occurs (it does happen)...
You could implement what you want as an extension.  Since a trailing %
in the format is undefined behaviour, you could have a version of
sprintf that interprets such an invalid conversion specifier as a
request to omit the trailing null character.

<snip>
-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#64809

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2015-07-06 15:48 -0700
Message-ID<96de34cd-daf8-42ac-be17-4a2b9d424bbc@googlegroups.com>
In reply to#64807
Ben Bacarisse wrote:
> A thought occurs (it does happen)... You could
> implement what you want as an extension.
> Since a trailing % in the format is undefined
> behaviour, you could have a version of sprintf
> that interprets such an invalid conversion
> specifier as a request to omit the trailing null
> character.

I love it.

Best regards,
Rick C. Hodgin

[toc] | [prev] | [next] | [standalone]


#64930

FromPhil Carmody <pc+usenet@asdf.org>
Date2015-07-08 20:09 +0300
Message-ID<87zj36d19c.fsf@bazspaz.fatphil.org>
In reply to#64807
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> <snip>
> >>> >> Rick C. Hodgin <rick.c.hodgin@gmail.com> wrote:
> >>> >> >  (1) Is there a version of sprintf() without a trailing NULL?
> <snip>
> > sprintf already has the right mechanism -- the % syntax.  You could
> > propose a new conversion specifier which, like %%, denotes a single
> > character -- a null.  It would mainly be useful in your memprintf
> > function:
> >
> >   memprintf(buffer, "%4u%!", year); // terminated -- min 5 bytes written
> >   memprintf(buffer, "%4u%!", year); // min 4 bytes written, no null
> 
> A thought occurs (it does happen)...
> You could implement what you want as an extension.  Since a trailing %
> in the format is undefined behaviour, you could have a version of
> sprintf that interprets such an invalid conversion specifier as a
> request to omit the trailing null character.

That is an exceptionally elegant way to solve the problem.

Phil
-- 
A well regulated militia, being necessary to the security of a free state,
the right of the people to keep and bear arms, shall be well regulated.

[toc] | [prev] | [next] | [standalone]


#64933

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2015-07-08 10:11 -0700
Message-ID<e83cec81-7c17-4630-94ff-2f47bdbc971b@googlegroups.com>
In reply to#64930
On Wednesday, July 8, 2015 at 1:10:00 PM UTC-4, Phil Carmody wrote:
> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> > Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> > <snip>
> > >>> >> Rick C. Hodgin <rick.c.hodgin@gmail.com> wrote:
> > >>> >> >  (1) Is there a version of sprintf() without a trailing NULL?
> > <snip>
> > > sprintf already has the right mechanism -- the % syntax.  You could
> > > propose a new conversion specifier which, like %%, denotes a single
> > > character -- a null.  It would mainly be useful in your memprintf
> > > function:
> > >
> > >   memprintf(buffer, "%4u%!", year); // terminated -- min 5 bytes written
> > >   memprintf(buffer, "%4u%!", year); // min 4 bytes written, no null
> > 
> > A thought occurs (it does happen)...
> > You could implement what you want as an extension.  Since a trailing %
> > in the format is undefined behaviour, you could have a version of
> > sprintf that interprets such an invalid conversion specifier as a
> > request to omit the trailing null character.
> 
> That is an exceptionally elegant way to solve the problem.

I couldn't agree more.  I've spent several brief few-minute sessions
thinking about this since it was posted.  It's beautiful.  Almost as
if those original designers were looking to this future need. :-)

Best regards,
Rick C. Hodgin

[toc] | [prev] | [next] | [standalone]


Page 1 of 4  [1] 2 3 4  Next page →

Back to top | Article view | comp.lang.c


csiph-web