I'm looking for a freeware c99 compiler for windows. I had intended to use
MS's Visual C++ Express and use its C capability. In the past with my MS
products, I've simply needed to make .c the filetype to invoke the C
compiler. Here's a link
http://www.microsoft.com/express/download/#webInstall
The download is 2.6 megs, which is near a reasonable size for a compiler,
but then setup.exe wants to download 87 megs of dot net framework hoggs
that I don't want on my machine.
In the past I've gone with Bloodshed, but I find myself unable to get the
shell to stay open so I can see some output.
The development environment for gcc is austere.
Anyone have another suggestion?
--
Women have simple tastes. They get pleasure out of the conversation of
children in arms and men in love.
H. L. Mencken
|
|
0
|
|
|
|
Reply
|
ron158 (171)
|
7/19/2008 12:49:46 AM |
|
On Jul 18, 5:49=A0pm, Ron Ford <r...@nowhere.net> wrote:
> I'm looking for a freeware c99 compiler for windows. =A0I had intended to=
use
> MS's Visual C++ Express and use its C capability. =A0In the past with my =
MS
> products, I've simply needed to make .c the filetype to invoke the C
> compiler. =A0Here's a link
>
> http://www.microsoft.com/express/download/#webInstall
>
> The download is 2.6 megs, which is near a reasonable size for a compiler,
> but then setup.exe wants to download 87 megs of dot net framework hoggs
> that I don't want on my machine.
>
> In the past I've gone with Bloodshed, but I find myself unable to get the
> shell to stay open so I can see some output.
>
> The development environment for gcc is austere.
>
> Anyone have another suggestion?
http://www.thefreecountry.com/compilers/cpp.shtml
http://www.compilers.net/Dir/Free/Compilers/CCpp.htm
http://www.freeprogrammingresources.com/cppcomp.html
http://www.freebyte.com/programming/cpp/
|
|
0
|
|
|
|
Reply
|
dcorbit (2696)
|
7/19/2008 12:57:22 AM
|
|
On Fri, 18 Jul 2008 17:57:22 -0700 (PDT), user923005 posted:
> On Jul 18, 5:49�pm, Ron Ford <r...@nowhere.net> wrote:
>> Anyone have another suggestion?
>
> http://www.thefreecountry.com/compilers/cpp.shtml
> http://www.compilers.net/Dir/Free/Compilers/CCpp.htm
> http://www.freeprogrammingresources.com/cppcomp.html
> http://www.freebyte.com/programming/cpp/
Thanks Dann, there seems to be many to choose from. I gave Cmega a try,
http://www.micro-ide.com/custom1.html ,but I don't think it's right for me,
until I know more about embedded systems. Their hello world program
compiles but does not build:
http://i33.tinypic.com/mra7ic.jpg
I'll give it another a try when I get more time.
--
Honor is simply the morality of superior men.
H. L. Mencken
|
|
0
|
|
|
|
Reply
|
ron158 (171)
|
7/19/2008 1:38:52 AM
|
|
Ron Ford wrote:
> I'm looking for a freeware c99 compiler for windows. I had intended to use
> MS's Visual C++ Express and use its C capability. In the past with my MS
> products, I've simply needed to make .c the filetype to invoke the C
> compiler. Here's a link
>
> http://www.microsoft.com/express/download/#webInstall
>
> The download is 2.6 megs, which is near a reasonable size for a compiler,
> but then setup.exe wants to download 87 megs of dot net framework hoggs
> that I don't want on my machine.
>
> In the past I've gone with Bloodshed, but I find myself unable to get the
> shell to stay open so I can see some output.
>
> The development environment for gcc is austere.
>
> Anyone have another suggestion?
Yes, use my compiler system lcc-win
The URL is below in my .sig.
Download 6MB.
o IDE
o C compiler (almost all C99)
o Extras like operator overloading and generic functions
o 105 digits precision floating point.
o bignums
o 128 bit integers
o Libraries: zip, perl regexp, matrix operations, and many others
--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
|
|
0
|
|
|
|
Reply
|
jacob4111 (1334)
|
7/19/2008 7:10:57 AM
|
|
Ron Ford wrote:
> I'm looking for a freeware c99 compiler for windows. I had intended
> to use MS's Visual C++ Express and use its C capability. In the past
It is not (and doesn't claim to be) a C99 compiler. It does (claim to)
comply to C89, as far as I know.
> with my MS products, I've simply needed to make .c the filetype to
> invoke the C compiler. Here's a link
some additional switches are needed to make it standard compliant.
> http://www.microsoft.com/express/download/#webInstall
>
> The download is 2.6 megs, which is near a reasonable size for a
> compiler, but then setup.exe wants to download 87 megs of dot net
> framework hoggs that I don't want on my machine.
>
> In the past I've gone with Bloodshed, but I find myself unable to get
> the shell to stay open so I can see some output.
>
> The development environment for gcc is austere.
gcc is not C99 compliant either.
> Anyone have another suggestion?
Bye, Jojo
|
|
0
|
|
|
|
Reply
|
nospam.jojo (1344)
|
7/19/2008 7:45:44 AM
|
|
jacob navia wrote:
> Ron Ford wrote:
>
>> I'm looking for a freeware c99 compiler for windows. I had
>> intended to use MS's Visual C++ Express and use its C capability.
>> In the past with my MS products, I've simply needed to make .c
>> the filetype to invoke the C compiler. Here's a link
>>
>> http://www.microsoft.com/express/download/#webInstall
>>
>> The download is 2.6 megs, which is near a reasonable size for a
>> compiler, but then setup.exe wants to download 87 megs of dot net
>> framework hoggs that I don't want on my machine.
>>
>> In the past I've gone with Bloodshed, but I find myself unable to
>> get the shell to stay open so I can see some output.
>>
>> The development environment for gcc is austere.
>>
>> Anyone have another suggestion?
>
> Yes, use my compiler system lcc-win
>
> The URL is below in my .sig.
>
> Download 6MB.
If you (Ron Ford) do that be VERY cautious about portability. It
appears that lcc-win does not detect various forbidden constructs
under C99, besides omitting several required things. It will
probably improve, but the author tends to resist suggestions. I
believe it also lacks version numbers, making it hard to keep track
of revisions.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
|
|
0
|
|
|
|
Reply
|
cbfalconer (19183)
|
7/19/2008 8:03:07 AM
|
|
Ron Ford wrote, On 19/07/08 02:38:
> On Fri, 18 Jul 2008 17:57:22 -0700 (PDT), user923005 posted:
>
>> On Jul 18, 5:49 pm, Ron Ford <r...@nowhere.net> wrote:
>
>>> Anyone have another suggestion?
>> http://www.thefreecountry.com/compilers/cpp.shtml
>> http://www.compilers.net/Dir/Free/Compilers/CCpp.htm
>> http://www.freeprogrammingresources.com/cppcomp.html
>> http://www.freebyte.com/programming/cpp/
>
> Thanks Dann, there seems to be many to choose from.
You should be aware that most compilers do not fully support C99. Some
important ones (e.g. MSVC) only support C90 and have made no noticable
progress towards C99. You might find the following useful:
http://clc-wiki.net/wiki/C_resources
> I gave Cmega a try,
> http://www.micro-ide.com/custom1.html ,but I don't think it's right for me,
> until I know more about embedded systems. Their hello world program
> compiles but does not build:
>
> http://i33.tinypic.com/mra7ic.jpg
>
> I'll give it another a try when I get more time.
For problems with a specific set of tools you will have to ask in
whatever groups/mailing-list/forums support it.
--
Flash Gordon
|
|
0
|
|
|
|
Reply
|
spam331 (4024)
|
7/19/2008 1:19:12 PM
|
|
On Sat, 19 Jul 2008 14:19:12 +0100, Flash Gordon posted:
> Ron Ford wrote, On 19/07/08 02:38:
>> On Fri, 18 Jul 2008 17:57:22 -0700 (PDT), user923005 posted:
>>
>>> On Jul 18, 5:49 pm, Ron Ford <r...@nowhere.net> wrote:
>>
>>>> Anyone have another suggestion?
>>> http://www.thefreecountry.com/compilers/cpp.shtml
>>> http://www.compilers.net/Dir/Free/Compilers/CCpp.htm
>>> http://www.freeprogrammingresources.com/cppcomp.html
>>> http://www.freebyte.com/programming/cpp/
>>
>> Thanks Dann, there seems to be many to choose from.
>
> You should be aware that most compilers do not fully support C99. Some
> important ones (e.g. MSVC) only support C90 and have made no noticable
> progress towards C99. You might find the following useful:
> http://clc-wiki.net/wiki/C_resources
I thought I read Jack Klein claiming that MS something Express was viable
as a C99 option. Oh well. I tried to fill the gap by installing Sun
Studio 12, but that doesn't work on OpenSolaris.:-(
The above link is helpful. From Dann's link yesterday, I found Visual
MingW, which is an IDE for windows. I think that information might be
newer than the information on C's wiki page.
> For problems with a specific set of tools you will have to ask in
> whatever groups/mailing-list/forums support it.
Thanks for saying that. It made me join their mailing list. I find
mailing lists to be hugely helpful for things like linmodems. One thing I
didn't get was the ability to debug from a pulldown menu. This screenshot
shows the attempt:
http://i34.tinypic.com/2q9x6jd.jpg
Also, the help menu is completely unpopulated, probably indicating that it
is a new project. If I can't get a debugging capability from this suite, I
will still be in the market for a new IDE.
--
Puritanism. The haunting fear that someone, somewhere, may be happy.
H. L. Mencken
|
|
0
|
|
|
|
Reply
|
ron158 (171)
|
7/20/2008 3:10:40 AM
|
|
On Sat, 19 Jul 2008 09:45:44 +0200, Joachim Schmitz posted:
> Ron Ford wrote:
>> The development environment for gcc is austere.
>
> gcc is not C99 compliant either.
How close is it?
Gfortran, which is gcc's compiler for fortran, is ahead of a lot of other
implementors as far as getting compliance to the next standard. So it is
that I can use ISO_C_BINDING with gfortran--new with F2003--but not my
other windows compiler with a sexy IDE.
I wonder how closely the situation for compliance with F2003 compares to
C99. There seems to be one issue that has everyone stumped: parameterized
derived types. Of course, C won't have PDT's, but is there a single issue
that seems to have implementors pulling their hair out?
--
No matter how long he lives, no man ever becomes as wise as the average
woman of forty-eight.
H. L. Mencken
|
|
0
|
|
|
|
Reply
|
ron158 (171)
|
7/20/2008 3:31:07 AM
|
|
In article <frmensiwqkls.1u1vlis516hku$.dlg@40tude.net>
Ron Ford <wade196884@netzero.net> wrote:
>I wonder how closely the situation for compliance with F2003 compares to
>C99. There seems to be one issue that has everyone stumped: parameterized
>derived types. Of course, C won't have PDT's, but is there a single issue
>that seems to have implementors pulling their hair out?
It seems to me that the answer to this question is "no". Different
"C99--" implementations (if I may call them that) are have different
parts that are "missing" or "broken" and there seems to be little if
any commonality.
GCC's set of missing/broken items is getting smaller, and for a
long time, the worst of them were due to C99 making slightly
*different* requirements from those for GNUC. (GNUC is the language
that GCC implemented; it was a lot like C99, only different. For
instance, the rules for VLAs and flexible array members were
different from those in C99.) That meant that changing the compiler
to do things the "C99 way" would break any code that depended on
GCC doing things the "GNUC way".
Other compilers had not implemented anything resembling those parts
of C99, and thus did not have "self-backwards-compatibility" problems
in the way.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40�39.22'N, 111�50.29'W) +1 801 277 2603
email: gmail (figure it out) http://web.torek.net/torek/index.html
|
|
0
|
|
|
|
Reply
|
nospam252 (1722)
|
7/20/2008 4:51:17 AM
|
|
Ron Ford wrote, On 20/07/08 04:10:
> On Sat, 19 Jul 2008 14:19:12 +0100, Flash Gordon posted:
<snip>
>> You should be aware that most compilers do not fully support C99. Some
>> important ones (e.g. MSVC) only support C90 and have made no noticable
>> progress towards C99. You might find the following useful:
>> http://clc-wiki.net/wiki/C_resources
>
> I thought I read Jack Klein claiming that MS something Express was viable
> as a C99 option.
It has a C89 (the old standard) option but not, as far as I am aware, a
C99 option.
> Oh well. I tried to fill the gap by installing Sun
> Studio 12, but that doesn't work on OpenSolaris.:-(
>
> The above link is helpful. From Dann's link yesterday, I found Visual
> MingW, which is an IDE for windows. I think that information might be
> newer than the information on C's wiki page.
<snip>
Please create an account and update anything that needs updating. It's a
Wiki and will only be as accurate and up to date as the last edit.
--
Flash Gordon
Providing the hosting for the CLC Wiki.
|
|
0
|
|
|
|
Reply
|
spam331 (4024)
|
7/20/2008 9:11:58 AM
|
|
Ron Ford <ron@nowhere.net> writes:
> On Sat, 19 Jul 2008 09:45:44 +0200, Joachim Schmitz posted:
>
>> Ron Ford wrote:
>
>>> The development environment for gcc is austere.
>>
>> gcc is not C99 compliant either.
>
> How close is it?
Closer than even their own status pages suggests:
http://gcc.gnu.org/gcc-4.3/c99status.html
That reports wide character support as "missing" but as far as I can
tell, the only thing missing is format checking for the w* family
(i.e. you don't get a compile-time warning for wprintf(L"%d"); but you
do for printf("%d);).
VLAs are reported as broken, but I can't find an example of how. All
the obscure cases I have tried work -- no doubt I am not being devious
enough. Can anyone else find one?
--
Ben.
|
|
0
|
|
|
|
Reply
|
ben.usenet (6515)
|
7/20/2008 9:26:40 AM
|
|
Ben Bacarisse wrote:
) VLAs are reported as broken, but I can't find an example of how. All
) the obscure cases I have tried work -- no doubt I am not being devious
) enough. Can anyone else find one?
Make a loop where you define a VLA at the beginning, of differing size.
Also, in the same loop, alloca() some memory, (and store the pointer in
an array.)
Of course, mixing VLA's and alloca() calls is nasty.
Is alloca() even part of C99 ?
SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
|
|
0
|
|
|
|
Reply
|
willem (1478)
|
7/20/2008 9:30:17 AM
|
|
Willem wrote, On 20/07/08 10:30:
> Ben Bacarisse wrote:
> ) VLAs are reported as broken, but I can't find an example of how. All
> ) the obscure cases I have tried work -- no doubt I am not being devious
> ) enough. Can anyone else find one?
>
> Make a loop where you define a VLA at the beginning, of differing size.
> Also, in the same loop, alloca() some memory, (and store the pointer in
> an array.)
>
> Of course, mixing VLA's and alloca() calls is nasty.
> Is alloca() even part of C99 ?
No, alloca() is not part of any C standard, so using it does not really
prove that there is a problem.
--
Flash Gordon
|
|
0
|
|
|
|
Reply
|
spam331 (4024)
|
7/20/2008 10:10:31 AM
|
|
Willem wrote:
>
> Of course, mixing VLA's and alloca() calls is nasty.
> Is alloca() even part of C99 ?
>
No.
--
Ian Collins.
|
|
0
|
|
|
|
Reply
|
ian-news (9880)
|
7/20/2008 10:23:55 AM
|
|
Willem <willem@stack.nl> writes:
> Ben Bacarisse wrote:
> ) VLAs are reported as broken, but I can't find an example of how. All
> ) the obscure cases I have tried work -- no doubt I am not being devious
> ) enough. Can anyone else find one?
>
> Make a loop where you define a VLA at the beginning, of differing size.
> Also, in the same loop, alloca() some memory, (and store the pointer in
> an array.)
Once a program uses alloca its behaviour is not governed by the C
standard alone. I could break VLAs with all sorts of stack-whacking
functions!
> Of course, mixing VLA's and alloca() calls is nasty.
> Is alloca() even part of C99 ?
No.
--
Ben.
|
|
0
|
|
|
|
Reply
|
ben.usenet (6515)
|
7/20/2008 10:40:10 AM
|
|
On Sun, 20 Jul 2008 10:26:40 +0100, Ben Bacarisse wrote:
> Ron Ford <ron@nowhere.net> writes:
>> On Sat, 19 Jul 2008 09:45:44 +0200, Joachim Schmitz posted:
>>> Ron Ford wrote:
>>>> The development environment for gcc is austere.
>>>
>>> gcc is not C99 compliant either.
>>
>> How close is it?
>
> Closer than even their own status pages suggests:
>
> http://gcc.gnu.org/gcc-4.3/c99status.html
>
> That reports wide character support as "missing" but as far as I can
> tell, the only thing missing is format checking for the w* family
#if __STDC_ISO_10646__
#define WE_HAVE_UNICODE 1
#else
#define WE_DO_NOT_HAVE_UNICODE 1
#endif
#include <wchar.h>
#if __STDC_ISO_10646__
#define WE_HAVE_UNICODE 1
#else
#define WE_DO_NOT_HAVE_UNICODE 1
#endif
#if WE_HAVE_UNICODE && WE_DO_NOT_HAVE_UNICODE
#error Your compiler is broken.
#endif
int main() {}
I cannot get this to compile with GCC. Can you?
And yes, this matters, because you may very well want to do:
#if __STDC_ISO_10646__
#include <wchar.h>
#endif
which just doesn't work right now.
|
|
0
|
|
|
|
Reply
|
truedfx (1926)
|
7/20/2008 10:42:36 AM
|
|
Harald van Dijk <truedfx@gmail.com> writes:
> On Sun, 20 Jul 2008 10:26:40 +0100, Ben Bacarisse wrote:
>> Ron Ford <ron@nowhere.net> writes:
>>> On Sat, 19 Jul 2008 09:45:44 +0200, Joachim Schmitz posted:
>>>> Ron Ford wrote:
>>>>> The development environment for gcc is austere.
>>>>
>>>> gcc is not C99 compliant either.
>>>
>>> How close is it?
>>
>> Closer than even their own status pages suggests:
>>
>> http://gcc.gnu.org/gcc-4.3/c99status.html
>>
>> That reports wide character support as "missing" but as far as I can
>> tell, the only thing missing is format checking for the w* family
>
> #if __STDC_ISO_10646__
> #define WE_HAVE_UNICODE 1
> #else
> #define WE_DO_NOT_HAVE_UNICODE 1
> #endif
>
> #include <wchar.h>
>
> #if __STDC_ISO_10646__
> #define WE_HAVE_UNICODE 1
> #else
> #define WE_DO_NOT_HAVE_UNICODE 1
> #endif
>
> #if WE_HAVE_UNICODE && WE_DO_NOT_HAVE_UNICODE
> #error Your compiler is broken.
> #endif
>
> int main() {}
>
> I cannot get this to compile with GCC. Can you?
Well... you /can/ do this:
gcc -std=c99 -pedantic -include features.h
As far as I can see that does not break any conforming programs and
does make gcc closer to C99. It certainly then compiler the above
correctly.
> And yes, this matters, because you may very well want to do:
>
> #if __STDC_ISO_10646__
> #include <wchar.h>
> #endif
Agreed. It is a problem -- the above is the academic answer (and may
well break other areas of conformance). The macro should be defined
by -std=c99 alone.
--
Ben.
|
|
0
|
|
|
|
Reply
|
ben.usenet (6515)
|
7/20/2008 11:34:03 AM
|
|
Ron Ford <ron@nowhere.net> wrote:
>
> I wonder how closely the situation for compliance with F2003 compares to
> C99. There seems to be one issue that has everyone stumped: parameterized
> derived types. Of course, C won't have PDT's, but is there a single issue
> that seems to have implementors pulling their hair out?
No, all of the major new features in C99 had already been implemented at
least once before the standard was approved. C99's problems are many:
lack of competition in the C compiler marketplace, lack of consumer
demand for full compliance, lack of resources (they're all busy trying
to implement C++), and incompatibility with existing extensions, just to
name a few big ones.
--
Larry Jones
How am I supposed to learn surgery if I can't dissect anything? -- Calvin
|
|
0
|
|
|
|
Reply
|
lawrence.jones2 (565)
|
7/20/2008 4:23:32 PM
|
|
On Sun, 20 Jul 2008 12:42:36 +0200, Harald van Dijk posted:
> On Sun, 20 Jul 2008 10:26:40 +0100, Ben Bacarisse wrote:
>> Ron Ford <ron@nowhere.net> writes:
>>> On Sat, 19 Jul 2008 09:45:44 +0200, Joachim Schmitz posted:
>>>> Ron Ford wrote:
>>>>> The development environment for gcc is austere.
>>>>
>>>> gcc is not C99 compliant either.
>>>
>>> How close is it?
>>
>> Closer than even their own status pages suggests:
>>
>> http://gcc.gnu.org/gcc-4.3/c99status.html
>>
>> That reports wide character support as "missing" but as far as I can
>> tell, the only thing missing is format checking for the w* family
>
> #if __STDC_ISO_10646__
> #define WE_HAVE_UNICODE 1
> #else
> #define WE_DO_NOT_HAVE_UNICODE 1
> #endif
>
> #include <wchar.h>
>
> #if __STDC_ISO_10646__
> #define WE_HAVE_UNICODE 1
> #else
> #define WE_DO_NOT_HAVE_UNICODE 1
> #endif
>
> #if WE_HAVE_UNICODE && WE_DO_NOT_HAVE_UNICODE
> #error Your compiler is broken.
> #endif
>
> int main() {}
>
> I cannot get this to compile with GCC. Can you?
I just fired this up in my new mingw IDE and got it to compile. I'm less
than surprised that it did, as it is my understanding that this is
equivalent to a hello world program, less the hello world:
http://i33.tinypic.com/wbxl54.jpg
>
> And yes, this matters, because you may very well want to do:
>
> #if __STDC_ISO_10646__
> #include <wchar.h>
> #endif
>
> which just doesn't work right now.
Don't know about this.
--
Criticism is prejudice made plausible.
H. L. Mencken
|
|
0
|
|
|
|
Reply
|
ron158 (171)
|
7/20/2008 6:45:06 PM
|
|
On Sun, 20 Jul 2008 12:23:32 -0400, lawrence.jones@siemens.com posted:
> Ron Ford <ron@nowhere.net> wrote:
>>
>> I wonder how closely the situation for compliance with F2003 compares to
>> C99. There seems to be one issue that has everyone stumped: parameterized
>> derived types. Of course, C won't have PDT's, but is there a single issue
>> that seems to have implementors pulling their hair out?
>
> No, all of the major new features in C99 had already been implemented at
> least once before the standard was approved. C99's problems are many:
> lack of competition in the C compiler marketplace, lack of consumer
> demand for full compliance, lack of resources (they're all busy trying
> to implement C++), and incompatibility with existing extensions, just to
> name a few big ones.
I don't know what other syntaxes have standards other than C, C++ and
fortran, so I'm not sure how well a person can draw on the histories.
Since F2003 has a feature that has never been realized in fortran and it's
a stumbling block for *all* implementations, I wonder if it ever happens
that a standard rolls back on a feature.
The muckity mucks are enclaving to approve a new standard (F08) with *zero*
currently-conforming implementations. Has this situation ever occured in C
or some other standardized syntax?
--
There are men so philosophical that they can see humor in their own
toothaches. But there has never lived a man so philosophical that he could
see the toothache in his own humor.
H. L. Mencken
|
|
0
|
|
|
|
Reply
|
ron158 (171)
|
7/20/2008 7:10:03 PM
|
|
On Sun, 20 Jul 2008 10:11:58 +0100, Flash Gordon posted:
> Ron Ford wrote, On 20/07/08 04:10:
>> The above link is helpful. From Dann's link yesterday, I found Visual
>> MingW, which is an IDE for windows. I think that information might be
>> newer than the information on C's wiki page.
> Please create an account and update anything that needs updating. It's a
> Wiki and will only be as accurate and up to date as the last edit.
It doesn't augur well for my editting skills that I can't find a means to
create an account. In the text, there is to be some control to click on at
the top of the page that is not a control I could find.
I use wiki frequently and have wondered how to contribute. The latest
mistake I saw was in the wiki for the play "Bedroom Farce" where the
characters are characterized as "philanderers." There's a grand total of
one kiss exchanged in the entire play.
--
War will never cease until babies begin to come into the world with larger
cerebrums and smaller adrenal glands.
H. L. Mencken
|
|
0
|
|
|
|
Reply
|
ron158 (171)
|
7/20/2008 7:38:25 PM
|
|
Flash Gordon <spam@flash-gordon.me.uk> writes:
> Willem wrote, On 20/07/08 10:30:
>> Ben Bacarisse wrote:
>> ) VLAs are reported as broken, but I can't find an example of how. All
>> ) the obscure cases I have tried work -- no doubt I am not being devious
>> ) enough. Can anyone else find one?
>> Make a loop where you define a VLA at the beginning, of differing
>> size.
>> Also, in the same loop, alloca() some memory, (and store the pointer in
>> an array.)
>> Of course, mixing VLA's and alloca() calls is nasty.
>> Is alloca() even part of C99 ?
>
> No, alloca() is not part of any C standard, so using it does not
> really prove that there is a problem.
Well, it doesn't prove that there's a *conformance* problem. If a
compiler is going to support alloca(), it would be nice if using it
didn't break VLAs. But that might not be practical, and the standard
doesn't require it.
One possible issue with VLAs is that a VLA is block-scoped, not
function-scoped (which I think Willem was alluding to above) --
<OT>whereas the memory allocated by alloca() is deallocated on
returning from the enclosing function</OT>.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
kst-u (21467)
|
7/20/2008 10:12:33 PM
|
|
On Jul 19, 8:49=A0am, Ron Ford <r...@nowhere.net> wrote:
> I'm looking for a freeware c99 compiler for windows. =A0I had intended to=
use
> MS's Visual C++ Express and use its C capability. =A0In the past with my =
MS
> products, I've simply needed to make .c the filetype to invoke the C
> compiler. =A0Here's a link
>
> http://www.microsoft.com/express/download/#webInstall
>
> The download is 2.6 megs, which is near a reasonable size for a compiler,
> but then setup.exe wants to download 87 megs of dot net framework hoggs
> that I don't want on my machine.
>
> In the past I've gone with Bloodshed, but I find myself unable to get the
> shell to stay open so I can see some output.
>
> The development environment for gcc is austere.
>
> Anyone have another suggestion?
You can try Eclipse and have the plug-in CDT (C/C++ Development Tool)
equipped together. The combination requires other compiler and
debugger.
|
|
0
|
|
|
|
Reply
|
lovecreatesbeauty (723)
|
7/21/2008 2:16:56 AM
|
|
Ron Ford <ron@nowhere.net> wrote:
>
> I don't know what other syntaxes have standards other than C, C++ and
> fortran, so I'm not sure how well a person can draw on the histories.
ADA, Algol, APL, Basic, COBOL, Modula-2, Pascal, and PL/I, just to name
a few.
> Since F2003 has a feature that has never been realized in fortran and it's
> a stumbling block for *all* implementations, I wonder if it ever happens
> that a standard rolls back on a feature.
Yes, it happens, but it's very unusual.
> The muckity mucks are enclaving to approve a new standard (F08) with *zero*
> currently-conforming implementations. Has this situation ever occured in C
> or some other standardized syntax?
Not in C, but I believe it has happened in C++ and probably in other
languages as well.
--
Larry Jones
I've never seen a sled catch fire before. -- Hobbes
|
|
0
|
|
|
|
Reply
|
lawrence.jones2 (565)
|
7/21/2008 7:53:15 PM
|
|
On Sat, 19 Jul 2008 04:03:07 -0400, CBFalconer posted:
> jacob navia wrote:
>> Ron Ford wrote:
>>
>>> I'm looking for a freeware c99 compiler for windows. I had
>>> intended to use MS's Visual C++ Express and use its C capability.
>>> In the past with my MS products, I've simply needed to make .c
>>> the filetype to invoke the C compiler. Here's a link
>>>
>>> http://www.microsoft.com/express/download/#webInstall
>>>
>>> The download is 2.6 megs, which is near a reasonable size for a
>>> compiler, but then setup.exe wants to download 87 megs of dot net
>>> framework hoggs that I don't want on my machine.
>>>
>>> In the past I've gone with Bloodshed, but I find myself unable to
>>> get the shell to stay open so I can see some output.
>>>
>>> The development environment for gcc is austere.
>>>
>>> Anyone have another suggestion?
>>
>> Yes, use my compiler system lcc-win
>>
>> The URL is below in my .sig.
>>
>> Download 6MB.
>
> If you (Ron Ford) do that be VERY cautious about portability. It
> appears that lcc-win does not detect various forbidden constructs
> under C99, besides omitting several required things. It will
> probably improve, but the author tends to resist suggestions. I
> believe it also lacks version numbers, making it hard to keep track
> of revisions.
I've used Jacob's lcc before and profited from it. At the time, I was
realizing that MVC6 wasn't going to do a lot of the things that I wanted
from a C99 compiler. Lcc helped me understand what I was looking for. In
particular, I remember finding the appropriate headers there for the first
time.
Meanwhile, Jacob has become less popular in clc, which I didn't think was
possible, and I've seen posts of his that looked angry and deranged, if not
drunk. For the record, I just wanted to state that the reason I didn't
download lcc was that I couldn't imagine wanting to admit to having a
problem and having to disclose that I was using lcc. I don't mean this as
a personal attack on Jacob, but I hope that he knows I like Frenchmen a
hell of lot better than my butthead Texas neighbors.
Another reason that I didn't go with lcc is that I'm looking for a compiler
for a specific purpose and think I've found a winner with WINAVR from
Atmel:
2.1 Manifest
GNU Binutils 2.18
Binary utilities for AVR target (including assembler, linker, etc.).
GNU Compiler Collection (GCC) 4.3.0
C language and C++ language compiler for AVR target. There are
caveats for using the C++ compiler. See the installed avr-libc
User Manual in the <InstallDir>\doc directory.
avr-libc CVS snapshot (1.6 branch, post 1.6.2)
C Standard Library for AVR.
AVR-Ada 0.5.2
Run Time System for the Ada compiler.
(Removed temporarily)
AVRDUDE 5.5
avrdude is an open source programmer software that is user extensible.
GNU Debugger (GDB) / Insight 6.6
GDB is a command-line debugger. Insight is GDB with a GUI!
AVaRICE 2.7
avarice is a program for interfacing the Atmel JTAG ICE to GDB and users
can debug their AVR. Use it in conjunction with GDB.
SimulAVR 0.1.2.5
simulavr is used in conjunction with GDB to provide AVR simulation.
SRecord 1.38
SRecord is a collection of powerful tools for manipulating EPROM load
files.
It reads and writes numerous EPROM file formats, and can perform many
different manipulations.
MFile
An automatic makefile generator for AVR GCC.
Programmers Notepad 2.0.7.667-devel
Programming editor and IDE. This editor includes the Scintilla editor
component.
//end abridged manifest
For interested parties:
http://winavr.sourceforge.net/
--
We must be willing to pay a price for freedom.
H. L. Mencken
|
|
0
|
|
|
|
Reply
|
ron158 (171)
|
7/22/2008 2:52:16 AM
|
|
Ron Ford wrote:
[snip]
>
> I've used Jacob's lcc before and profited from it. At the time, I was
> realizing that MVC6 wasn't going to do a lot of the things that I wanted
> from a C99 compiler. Lcc helped me understand what I was looking for. In
> particular, I remember finding the appropriate headers there for the first
> time.
>
OK, so you used my work and it was useful for you. Nice.
> Meanwhile, Jacob has become less popular in clc, which I didn't think was
> possible,
Why should I be popular with the "regulars" here? I am completely
opposed to that people.
> and I've seen posts of his that looked angry and deranged, if not
> drunk.
An example of a "drunk" post is yours. See below.
> For the record, I just wanted to state that the reason I didn't
> download lcc was that I couldn't imagine wanting to admit to having a
> problem and having to disclose that I was using lcc.
So, since I am not "popular" with the regulars here, you are afraid
of "disclosing" that my work was useful to you. You fear that the
regulars will leave you out in the cold, poor soul...
--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
|
|
0
|
|
|
|
Reply
|
jacob4111 (1334)
|
7/22/2008 1:14:49 PM
|
|
In article <g64mhs$nk9$1@aioe.org>, jacob navia <jacob@nospam.org> wrote:
>Ron Ford wrote:
....
>> For the record, I just wanted to state that the reason I didn't
>> download lcc was that I couldn't imagine wanting to admit to having a
>> problem and having to disclose that I was using lcc.
>
>So, since I am not "popular" with the regulars here, you are afraid
>of "disclosing" that my work was useful to you. You fear that the
>regulars will leave you out in the cold, poor soul...
That *is* basically what it boils down to. Assuming that you
(hypothetical "you") are so desperate for help (say, to escape brutal
third world squalor) that you're willing to take it from the jerks of
CLC, then it *is* in your interest to not be seen as being friendly with
Jacob. The regs will not look kindly upon that.
All of life is just the grade school playground. Most of us never
mature beyond that point. And CLC is demonstrable proof of this.
|
|
0
|
|
|
|
Reply
|
gazelle2 (1306)
|
7/22/2008 4:13:22 PM
|
|
On Tue, 22 Jul 2008 16:13:22 +0000 (UTC), Kenny McCormack posted:
> In article <g64mhs$nk9$1@aioe.org>, jacob navia <jacob@nospam.org> wrote:
>>Ron Ford wrote:
> ...
>>> For the record, I just wanted to state that the reason I didn't
>>> download lcc was that I couldn't imagine wanting to admit to having a
>>> problem and having to disclose that I was using lcc.
>>
>>So, since I am not "popular" with the regulars here, you are afraid
>>of "disclosing" that my work was useful to you. You fear that the
>>regulars will leave you out in the cold, poor soul...
>
> That *is* basically what it boils down to. Assuming that you
> (hypothetical "you") are so desperate for help (say, to escape brutal
> third world squalor) that you're willing to take it from the jerks of
> CLC, then it *is* in your interest to not be seen as being friendly with
> Jacob. The regs will not look kindly upon that.
>
> All of life is just the grade school playground. Most of us never
> mature beyond that point. And CLC is demonstrable proof of this.
I don't fear disclosing that Jacob's work has been useful to me. I just
did.
My current project has to do with embedded systems, and lcc isn't the best
tool.
If clc were a playground soccer game, Jacob would be my first pick.
--
In this world of sin and sorrow there is always something to be thankful
for; as for me, I rejoice that I am not a Republican.
H. L. Mencken
|
|
0
|
|
|
|
Reply
|
ron158 (171)
|
7/23/2008 12:49:45 AM
|
|
Ron Ford said:
<snip>
> If clc were a playground soccer game, Jacob would be my first pick.
Really? Mine would be Chris Torek.
If, on the other hand, it were a basketball game, it would all depend on
who were refereeing. ("I tried it and it worked fine...")
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
7/23/2008 1:41:08 AM
|
|
On Wed, 23 Jul 2008 01:41:08 +0000, Richard Heathfield posted:
> Ron Ford said:
>
> <snip>
>
>> If clc were a playground soccer game, Jacob would be my first pick.
>
> Really? Mine would be Chris Torek.
Dude, I've played soccer in SLC and can assure you that Torek would have to
be a goalie, if Keith didn't antecedently have to be.
But since you chose a player, I'll use the ISO_C_BINDING and select Richard
Maine from a common extension.
>
> If, on the other hand, it were a basketball game, it would all depend on
> who were refereeing. ("I tried it and it worked fine...")
I'm gonna guess that I'm the only fella in clc who can dunk it. South
Chicago.
--
What men value in this world is not rights but privileges.
H. L. Mencken
|
|
0
|
|
|
|
Reply
|
ron158 (171)
|
7/23/2008 2:32:48 AM
|
|
Ron Ford said:
> On Wed, 23 Jul 2008 01:41:08 +0000, Richard Heathfield posted:
>
>> Ron Ford said:
>>
>> <snip>
>>
>>> If clc were a playground soccer game, Jacob would be my first pick.
>>
>> Really? Mine would be Chris Torek.
>
> Dude, I've played soccer in SLC and can assure you that Torek would have
> to be a goalie, if Keith didn't antecedently have to be.
>
> But since you chose a player, I'll use the ISO_C_BINDING and select
> Richard Maine from a common extension.
>
>>
>> If, on the other hand, it were a basketball game, it would all depend on
>> who were refereeing. ("I tried it and it worked fine...")
>
> I'm gonna guess that I'm the only fella in clc who can dunk it. South
> Chicago.
I understood every individual word in your reply; nevertheless, I didn't
understand a single word of it.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
7/23/2008 4:24:35 AM
|
|
"Richard Heathfield" <rjh@see.sig.invalid> wrote in message
news:tfadnXfEvJeBFhvVnZ2dnUVZ8rKdnZ2d@bt.com...
> Ron Ford said:
>
> <snip>
>
>> If clc were a playground soccer game, Jacob would be my first pick.
>
> Really? Mine would be Chris Torek.
You guys are nuts. I'm going with Pele in his prime.
;-)
** Posted from http://www.teranews.com **
|
|
0
|
|
|
|
Reply
|
dcorbit (2696)
|
7/23/2008 7:09:58 AM
|
|
On Wed, 23 Jul 2008 00:09:58 -0700, Dann Corbit posted:
> "Richard Heathfield" <rjh@see.sig.invalid> wrote in message
> news:tfadnXfEvJeBFhvVnZ2dnUVZ8rKdnZ2d@bt.com...
>> Ron Ford said:
>>
>> <snip>
>>
>>> If clc were a playground soccer game, Jacob would be my first pick.
>>
>> Really? Mine would be Chris Torek.
>
> You guys are nuts. I'm going with Pele in his prime.
> ;-)
Maradonna was the best I ever saw. It's interesting to think of what a
soccer game with clc would look like, but it is a sheer impossibility to
have a casual ballgame among persons who would have to burn an average of a
hundred gallons of fossil fuel to attend.
I think the etymology of "Torek" might actually be close to goalie. The
-ik, uk, ek ending indicates "one who does" in languages like Russian and
Polish. "Tor" could be gate or goal.
Regarding basketball, Barack Omaba is not an unusual Chicagoan to be able
to hit a three-pointer. It speaks to his poise, athleticism and
flexibility that he could go one for one from beyond the arc. My brother
hits from farther out, truly downtown, routinely.
>
> ** Posted from http://www.teranews.com **
Dann, did you change your NSP? I had a google killfilter that was hiting
your posts before.
--
War will never cease until babies begin to come into the world with larger
cerebrums and smaller adrenal glands. 2
H. L. Mencken
|
|
0
|
|
|
|
Reply
|
ron158 (171)
|
7/24/2008 8:32:40 PM
|
|
>>> Ron Ford said:
>>>> If clc were a playground soccer game, Jacob would be my first pick.
>> "Richard Heathfield" <rjh@see.sig.invalid> wrote in message
>> news:tfadnXfEvJeBFhvVnZ2dnUVZ8rKdnZ2d@bt.com...
>>> Really? Mine would be Chris Torek.
>On Wed, 23 Jul 2008 00:09:58 -0700, Dann Corbit posted:
>> You guys are nuts. I'm going with Pele in his prime.
>> ;-)
In article <riqlu8dork8r.awv2an3ej8r0.dlg@40tude.net>
Ron Ford <ron@nowhere.net> wrote:
>I think the etymology of "Torek" might actually be close to goalie.
The word "torek" in Slovenian means "tuesday", apparently. The
name also fits the pattern of Vulcan names, which is perhaps more
appropriate. :-)
If I were to play soccer, goalie might be the most appropriate
position anyway, as I have a bad knee (left leg) and a bad foot
(right leg) thanks to getting hit by a car. (I was in a crosswalk
-- Richard Heathfield would call it a zebra crossing -- at a four-way
stop; the driver was in a 1974 Toyota Land Cruiser.) The main side
effect of these today is that I cannot do "high impact" aerobics,
and have to wear knee wraps when doing squats with anything over
about 250 pounds.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40�39.22'N, 111�50.29'W) +1 801 277 2603
email: gmail (figure it out) http://web.torek.net/torek/index.html
|
|
0
|
|
|
|
Reply
|
nospam252 (1722)
|
7/26/2008 10:53:21 AM
|
|
Chris Torek said:
<snip>
> In article <riqlu8dork8r.awv2an3ej8r0.dlg@40tude.net>
> Ron Ford <ron@nowhere.net> wrote:
>>I think the etymology of "Torek" might actually be close to goalie.
>
> The word "torek" in Slovenian means "tuesday", apparently. The
> name also fits the pattern of Vulcan names, which is perhaps more
> appropriate. :-)
In Polish (another Slavic language), "Tuesday" is "wtorek" - pretty close.
Oh, and "torebka" means "bag". :-)
<snip>
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
7/26/2008 1:05:18 PM
|
|
On 24 Jul 2008 at 20:32, Ron Ford wrote:
> It's interesting to think of what a soccer game with clc would look
> like
Given that clc is full of egomaniacs, it's hard to imagine finding 11 of
them that could play as a team for 90 minutes without ripping each other
to shreds.
But my money would be on CBF scoring an awful lot of own goals.
|
|
0
|
|
|
|
Reply
|
nospam59 (9755)
|
7/26/2008 1:56:48 PM
|
|
> On Sun, 20 Jul 2008 12:34:03 +0100, Ben Bacarisse wrote:
> Well... you /can/ do this:
>
> gcc -std=c99 -pedantic -include features.h
>
> As far as I can see that does not break any conforming programs and
> does make gcc closer to C99. It certainly then compiler the above
> ..SNIP...
I write network programs and yes I uses Sockets all the time. I mainly
use it because of 3 reasons:
1.) // style comments
2.) for( int i = 0; ... ) , to keep i localized to the loop
3.) snprintf (replacement for sprintf)
Regarding portability, I am focused on Linux only. I don't work on any
other OS. So, Do you guys advise to use -std=c99 as compiler option ?
--
www.lispmachine.wordpress.com
my email is @ the above blog
check the "About Myself" page
|
|
0
|
|
|
|
Reply
|
sunrise2 (598)
|
8/4/2008 11:55:16 AM
|
|
arnuld wrote:
>> On Sun, 20 Jul 2008 12:34:03 +0100, Ben Bacarisse wrote:
>
>> Well... you /can/ do this:
>>
>> gcc -std=c99 -pedantic -include features.h
>>
>> As far as I can see that does not break any conforming programs and
>> does make gcc closer to C99. It certainly then compiler the above
>
>> ..SNIP...
>
>
> I write network programs and yes I uses Sockets all the time. I mainly
> use it because of 3 reasons:
>
> 1.) // style comments
> 2.) for( int i = 0; ... ) , to keep i localized to the loop
> 3.) snprintf (replacement for sprintf)
>
>
> Regarding portability, I am focused on Linux only. I don't work on any
> other OS. So, Do you guys advise to use -std=c99 as compiler option ?
If you focused only on Linux you might as well take advantage of gcc
specific, Linux specific and POSIX extensions. For gcc
use '-std=gnu99'. It might still be useful to keep portable and
non-portable functionality separate, in case you ever change your mind.
Look-up the "feature test macros" functionality of GNU libc. The POSIX
documentation is also freely available online. For more details go to
comp.unix.programmer and comp.os.linux.development.[apps/system].
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/4/2008 12:17:38 PM
|
|
On Mon, 04 Aug 2008 17:47:38 +0530, santosh wrote:
> arnuld wrote:
>> I write network programs and yes I uses Sockets all the time. I mainly
>> use it because of 3 reasons:
>>
>> 1.) // style comments
>> 2.) for( int i = 0; ... ) , to keep i localized to the loop
>> 3.) snprintf (replacement for sprintf)
>>
>> Regarding portability, I am focused on Linux only. I don't work on any
>> other OS. So, Do you guys advise to use -std=c99 as compiler option ?
>
> If you focused only on Linux you might as well take advantage of gcc
> specific,
To both arnuld and santosh: please don't assume that everyone on Linux
uses gcc. At the very least, there's Intel's compiler, but there are other
useful compilers as well.
> Linux specific and POSIX extensions.
Fair enough.
> For gcc use '-std=gnu99'.
I would recommend sticking with -std=c99. Even if you want to make use of
GNU-specific features, you can use -std=c99; you'll usually just need to
either deal with warnings or clearly mark your use of extensions. This, in
my opinion, is a good thing.
> It might still be useful to keep portable and non-portable functionality
> separate, in case you ever change your mind.
Well, we had similar ideas apparently, but different methods.
> Look-up the "feature test macros" functionality of GNU libc. The POSIX
> documentation is also freely available online. For more details go to
> comp.unix.programmer and comp.os.linux.development.[apps/system].
|
|
0
|
|
|
|
Reply
|
truedfx (1926)
|
8/4/2008 7:23:09 PM
|
|
arnuld wrote:
>> Ben Bacarisse wrote:
>
>> Well... you /can/ do this:
>>
>> gcc -std=c99 -pedantic -include features.h
>>
>> As far as I can see that does not break any conforming programs
>> and does make gcc closer to C99. It certainly then compiler the
>> above
>
>> ..SNIP...
>
> I write network programs and yes I uses Sockets all the time. I
> mainly use it because of 3 reasons:
>
> 1.) // style comments
> 2.) for( int i = 0; ... ) , to keep i localized to the loop
> 3.) snprintf (replacement for sprintf)
>
> Regarding portability, I am focused on Linux only. I don't work
> on any other OS. So, Do you guys advise to use -std=c99 as
> compiler option ?
You are much more portable relying on the C90 standard. The result
is almost always compatible with C99 (the only exception I know of
has to do with the modulus operator and negative values). You
can't use the // comments, but that is no loss IMO.
With gcc, I habitually use:
-W -Wall -ansi -pedantic -Wwrite-strings -Wfloat-equal -ftrapv ...
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
|
|
0
|
|
|
|
Reply
|
cbfalconer (19183)
|
8/4/2008 8:47:21 PM
|
|
> On Mon, 04 Aug 2008 16:47:21 -0400, CBFalconer wrote:
> You are much more portable relying on the C90 standard. The result
> is almost always compatible with C99 (the only exception I know of
> has to do with the modulus operator and negative values). You
> can't use the // comments, but that is no loss IMO.
what about snprintf, which saves from overflowing the array attacks. And
what about localization of index integers like for( in i = 0...) .
I know you are trying to help me, what I am saying that the softwares I am
paid to write for are designed only to run on Linux and nothing else.
> With gcc, I habitually use:
> -W -Wall -ansi -pedantic -Wwrite-strings -Wfloat-equal -ftrapv ...
Doesn't -Wextra give access to -Wwrite-strings and -Wfloat-equal ?
--
www.lispmachine.wordpress.com
my email is @ the above blog
check the "About Myself" page
|
|
0
|
|
|
|
Reply
|
sunrise2 (598)
|
8/5/2008 2:08:18 AM
|
|
> On Mon, 04 Aug 2008 21:23:09 +0200, Harald van Dijk wrote:
> To both arnuld and santosh: please don't assume that everyone on Linux
> uses gcc. At the very least, there's Intel's compiler, but there are
> other useful compilers as well.
Exactly. And the focus I am paid for is Linux & GCC centric.
> I would recommend sticking with -std=c99. Even if you want to make use
> of GNU-specific features, you can use -std=c99; you'll usually just need
> to either deal with warnings or clearly mark your use of extensions.
> This, in my opinion, is a good thing.
That seems like a sound advice ;)
--
www.lispmachine.wordpress.com
my email is @ the above blog
check the "About Myself" page
|
|
0
|
|
|
|
Reply
|
sunrise2 (598)
|
8/5/2008 2:12:23 AM
|
|
> On Tue, 05 Aug 2008 10:58:20 +0000, Richard Heathfield wrote:
> Using snprintf does not guarantee this. You have to use it /properly/. And
> if you use sprintf properly, you get the same safety. So snprintf isn't
> actually all that big a deal.
Aye.. did not know that :( , will check archives first and then ask
> But it seems from other stuff you've said that you're only interested in
> Linux, which is fine, but it does suggest that you'd be better off asking
> about flags in a group dealing with your implementation rather than a
> group dealing with the C language.
oops!
--
www.lispmachine.wordpress.com
my email is @ the above blog
check the "About Myself" page
|
|
0
|
|
|
|
Reply
|
sunrise2 (598)
|
8/5/2008 6:09:18 AM
|
|
> On Tue, 05 Aug 2008 10:58:20 +0000, Richard Heathfield wrote:
> Using snprintf does not guarantee this. You have to use it /properly/.
> And if you use sprintf properly, you get the same safety. So snprintf
> isn't actually all that big a deal.
I searched the archives and really much confused. "Ben Pfaff" says:
The point is that strncpy() is as dangerous
as strcpy() if it isn't used with care.
and regarding sprintf vs snprint I get this from "Aleksander Nabaglo"
1: Calculate needed buffer size,
2: Use assert: bug will not be hidden.
int nsp=0;
sprintf(buf, " ..... %n", /* args */ , &nsp);
if(buf_size <= nsp) { assert(0 & " buf[] too short ");
exit(SOME_ERROR_CODE);
is that okay ?
I also heard from someone that using assert() in code going to be shipped
is a bad idea. All assert statement, before the delivery, must be removed.
Do you have some code for safe sprintf() ?
> But it seems from other stuff you've said that you're only interested in
> Linux, which is fine,
I actually thought snprint() will save me from buffer problems and now
after a little search I can see that I was using it blindly. Anyway, I
still like the for( int i = 0;..) localization in C99. I don't like my
programs to be polluted by some index numbers when I know I am on Linux
for next decade, at least.
--
www.lispmachine.wordpress.com
my email is @ the above blog
check the "About Myself" page
|
|
0
|
|
|
|
Reply
|
sunrise2 (598)
|
8/5/2008 6:32:20 AM
|
|
arnuld wrote:
>> On Mon, 04 Aug 2008 16:47:21 -0400, CBFalconer wrote:
>
>
>> You are much more portable relying on the C90 standard. The result
>> is almost always compatible with C99 (the only exception I know of
>> has to do with the modulus operator and negative values). You
>> can't use the // comments, but that is no loss IMO.
>
> what about snprintf, which saves from overflowing the array attacks.
If you can get the second parameter of snprintf right, you can construct
a perfectly defined call to sprintf too.
> And what about localization of index integers like for( in i = 0...) .
{
int i;
for (...)
...
}
> I know you are trying to help me, what I am saying that the softwares
> I am paid to write for are designed only to run on Linux and nothing
> else.
Fair enough, though if all else is equal, a more portable solution is
always a better investment for the future.
>> With gcc, I habitually use:
>> -W -Wall -ansi -pedantic -Wwrite-strings -Wfloat-equal -ftrapv ...
>
> Doesn't -Wextra give access to -Wwrite-strings and -Wfloat-equal ?
Not according to the gcc documentation I have.
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/5/2008 10:43:35 AM
|
|
arnuld said:
>> On Mon, 04 Aug 2008 16:47:21 -0400, CBFalconer wrote:
>
>
>> You are much more portable relying on the C90 standard. The result
>> is almost always compatible with C99 (the only exception I know of
>> has to do with the modulus operator and negative values). You
>> can't use the // comments, but that is no loss IMO.
>
> what about snprintf, which saves from overflowing the array attacks.
Using snprintf does not guarantee this. You have to use it /properly/. And
if you use sprintf properly, you get the same safety. So snprintf isn't
actually all that big a deal.
But it seems from other stuff you've said that you're only interested in
Linux, which is fine, but it does suggest that you'd be better off asking
about flags in a group dealing with your implementation rather than a
group dealing with the C language.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/5/2008 10:58:20 AM
|
|
Richard Heathfield wrote:
> arnuld said:
<snip>
>> what about snprintf, which saves from overflowing the array attacks.
>
> Using snprintf does not guarantee this. You have to use it /properly/.
> And if you use sprintf properly, you get the same safety. So snprintf
> isn't actually all that big a deal.
Well, the difference is that with snprintf, as long as the second
parameter is correct you are guaranteed to avoid a buffer overrun,
while with sprintf you need to be sure in advance that the second
argument will not overrun the first, and this could be quite difficult
in some cases.
<snip>
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/5/2008 11:02:42 AM
|
|
santosh said:
> Richard Heathfield wrote:
>> arnuld said:
>
> <snip>
>
>>> what about snprintf, which saves from overflowing the array attacks.
>>
>> Using snprintf does not guarantee this. You have to use it /properly/.
>> And if you use sprintf properly, you get the same safety. So snprintf
>> isn't actually all that big a deal.
>
> Well, the difference is that with snprintf, as long as the second
> parameter
(You mean the second argument expression, presumably.)
> is correct you are guaranteed to avoid a buffer overrun,
No, you're not, because your /first/ argument could be incorrect:
#define OOPS 6
char intended[32] = {0};
char actual[OOPS] = {0};
snprintf(actual, sizeof intended, "Hello, world");
or your copying semantics might be screwed:
snprintf(ohdear, sizeof ohdear, "%d: %s", i, ohdear);
(in which case the behaviour is undefined, and one possible outcome of
undefined behaviour is that a buffer overrun occurs).
> while with sprintf you need to be sure in advance that the second
> argument will not overrun the first, and this could be quite difficult
> in some cases.
You need to be sure with snprintf too, otherwise you'll silently lose data.
No, it doesn't have to be silent, because you could be listening - but by
the time you've taken the trouble to add the code to listen for data loss
and take corrective action to ensure that no data loss occurs after all,
you might as well have used sprintf in the first place.
Arbitrary data loss might be okay for some people, but it's something I try
to avoid if I can.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/5/2008 11:36:23 AM
|
|
Richard Heathfield wrote:
> santosh said:
>
>> Richard Heathfield wrote:
>>> arnuld said:
>>
>> <snip>
>>
>>>> what about snprintf, which saves from overflowing the array
>>>> attacks.
>>>
>>> Using snprintf does not guarantee this. You have to use it
>>> /properly/. And if you use sprintf properly, you get the same
>>> safety. So snprintf isn't actually all that big a deal.
>>
>> Well, the difference is that with snprintf, as long as the second
>> parameter
>
> (You mean the second argument expression, presumably.)
>
>> is correct you are guaranteed to avoid a buffer overrun,
>
> No, you're not, because your /first/ argument could be incorrect:
Yes. But when I said "correct" I meant that it was the correct value for
the first argument. I realise in hindsight that I should've explicitly
mentioned this.
> #define OOPS 6
>
> char intended[32] = {0};
> char actual[OOPS] = {0};
>
> snprintf(actual, sizeof intended, "Hello, world");
The second argument is "wrong", isn't it? :-)
> or your copying semantics might be screwed:
>
> snprintf(ohdear, sizeof ohdear, "%d: %s", i, ohdear);
>
> (in which case the behaviour is undefined, and one possible outcome of
> undefined behaviour is that a buffer overrun occurs).
Agreed.
>> while with sprintf you need to be sure in advance that the second
>> argument will not overrun the first, and this could be quite
>> difficult in some cases.
>
> You need to be sure with snprintf too, otherwise you'll silently lose
> data.
But this is, in most cases, better than invoking undefined behaviour
with a buffer overrun, since it's possible to recover and retry.
> No, it doesn't have to be silent, because you could be listening
> - but by the time you've taken the trouble to add the code to listen
> for data loss and take corrective action to ensure that no data loss
> occurs after all,
Exactly.
> you might as well have used sprintf in the first place.
But the difference is that with sprintf you need to know this in
advance, while with snprintf you can "adapt as you go", so to speak.
This offloads the tricky bit of figuring out exactly how long our
buffer needs to be to snprintf itself.
> Arbitrary data loss might be okay for some people, but it's something
> I try to avoid if I can.
One can use snprintf *and* avoid arbitrary data loss. You need to cache
all your arguments beyond the first, determine the buffer size needed
by a call to snprintf, malloc the buffer (or perhaps a VLA), and write
to it. I admit that this is more complicated than one would like, but
sprintf, by overrunning the buffer, invokes a problem that cannot be
recovered from with Standard C.
Both are perfectly usable if adequate care is taken, but snprintf does
add a small convenience that I personally like. And it's certainly
among the more widely implemented of C99's many additions.
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/5/2008 12:06:35 PM
|
|
On Aug 4, 3:47 pm, CBFalconer <cbfalconer@yahoo.com> wrote:
> arnuld wrote:
> >> Ben Bacarisse wrote:
>
> >> Well... you /can/ do this:
>
> >> gcc -std=c99 -pedantic -include features.h
>
> >> As far as I can see that does not break any conforming programs
> >> and does make gcc closer to C99. It certainly then compiler the
> >> above
>
> >> ..SNIP...
>
> > I write network programs and yes I uses Sockets all the time. I
> > mainly use it because of 3 reasons:
>
> > 1.) // style comments
> > 2.) for( int i = 0; ... ) , to keep i localized to the loop
> > 3.) snprintf (replacement for sprintf)
>
> > Regarding portability, I am focused on Linux only. I don't work
> > on any other OS. So, Do you guys advise to use -std=c99 as
> > compiler option ?
>
> You are much more portable relying on the C90 standard. The result
> is almost always compatible with C99 (the only exception I know of
> has to do with the modulus operator and negative values).
Here are others:
o No implicit function declarations (so you can't use a function
without defining or declaring it first)
o No implicit function return type (so you can't omit the return
type of a function and let it default to int)
o It's illegal to have a return statement with no expression in
a non-void function (in previous versions this would cause
undefined behavior)
Just to name the most obvious ones...
> You
> can't use the // comments, but that is no loss IMO.
>
One man's trash is another man's treasure :) That's one of the BIGGEST
losses, IMO (along with being unable to mix statements and
declarations).
<snip>
Anyway, I don't see any portability losses if you're working on common
platforms, let alone if you're working on a *single* platform, not to
mention if that platform happens to be Linux!
Sebastian
|
|
0
|
|
|
|
Reply
|
s0suk3 (372)
|
8/5/2008 12:17:55 PM
|
|
santosh said:
> Richard Heathfield wrote:
>> santosh said:
<snip>
>>> Well, the difference is that with snprintf, as long as the second
>>> parameter
>>
>> (You mean the second argument expression, presumably.)
>>
>>> is correct you are guaranteed to avoid a buffer overrun,
>>
>> No, you're not, because your /first/ argument could be incorrect:
>
> Yes. But when I said "correct" I meant that it was the correct value for
> the first argument. I realise in hindsight that I should've explicitly
> mentioned this.
>
>> #define OOPS 6
>>
>> char intended[32] = {0};
>> char actual[OOPS] = {0};
>>
>> snprintf(actual, sizeof intended, "Hello, world");
>
> The second argument is "wrong", isn't it? :-)
The intended line is:
snprintf(intended, sizeof intended, "Hello, world");
so it's the first arg, not the second, that needs to be corrected. My
point, which is now in danger of being concealed by good-humoured banter,
is that there are almost always several ways to get things wrong.
<snip>
>>> while with sprintf you need to be sure in advance that the second
>>> argument will not overrun the first, and this could be quite
>>> difficult in some cases.
>>
>> You need to be sure with snprintf too, otherwise you'll silently lose
>> data.
>
> But this is, in most cases, better than invoking undefined behaviour
> with a buffer overrun, since it's possible to recover and retry.
Better surely to do neither, but to get it right first time instead.
>> No, it doesn't have to be silent, because you could be listening
>> - but by the time you've taken the trouble to add the code to listen
>> for data loss and take corrective action to ensure that no data loss
>> occurs after all,
>
> Exactly.
>
>> you might as well have used sprintf in the first place.
>
> But the difference is that with sprintf you need to know this in
> advance, while with snprintf you can "adapt as you go", so to speak.
Mostly you do know in advance. On the rare occasions when you don't, it's
generally easy enough to find out.
> This offloads the tricky bit of figuring out exactly how long our
> buffer needs to be to snprintf itself.
The way I see it is that if you know that your buffer is already long
enough, you don't need to offload this figuring because it's already done.
And if it isn't long enough (or at least you don't know whether it is),
you're not ready to construct the output yet, and so you're not really
using snprintf as a string-builder but as a calculator, after which you
must allocate storage for the buffer - which you *now* know *for sure* is
long enough, right? And so you might as well use sprintf for the final
stage of building the string.
>> Arbitrary data loss might be okay for some people, but it's something
>> I try to avoid if I can.
>
> One can use snprintf *and* avoid arbitrary data loss.
Yes, but you can say that about almost any function - for example, you can
use isalpha and avoid arbitrary data loss. The point is that snprintf is
wrongly touted as a "safe" alternative to sprintf whereas in fact it is no
such thing (much as strncpy is falsely touted as a "safe" alternative to
strcpy).
> You need to cache
> all your arguments beyond the first, determine the buffer size needed
> by a call to snprintf, malloc the buffer (or perhaps a VLA), and write
> to it. I admit that this is more complicated than one would like, but
> sprintf, by overrunning the buffer, invokes a problem that cannot be
> recovered from with Standard C.
To use sprintf safely, you first need to find out how big your output
buffer needs to be - and once you've done that, it's just as safe as
snprintf and considerably more portable.
> Both are perfectly usable if adequate care is taken,
Right.
> but snprintf does
> add a small convenience that I personally like. And it's certainly
> among the more widely implemented of C99's many additions.
If you know for sure that all your target platforms support it (with the
same semantics on each platform), that's a perfectly sensible approach. I
just can't help thinking that it's a risky strategy, that's all - stuff we
know "for sure" has an alarming habit of turning out not to be true in six
months time.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/5/2008 12:54:57 PM
|
|
arnuld wrote:
>> On Tue, 05 Aug 2008 10:58:20 +0000, Richard Heathfield wrote:
>
>
>> Using snprintf does not guarantee this. You have to use it
>> /properly/. And if you use sprintf properly, you get the same safety.
>> So snprintf isn't actually all that big a deal.
>
> I searched the archives and really much confused. "Ben Pfaff" says:
>
> The point is that strncpy() is as dangerous
> as strcpy() if it isn't used with care.
This is true. In particular you can cause a buffer overrun just as
easily with strncpy as you can with strcpy.
In fact you cause a buffer overrun with just about every Standard C
function that takes a pointer to one. The only solution to this would
be either interpreting the code or adding runtime checks for all
pointer operations.
> and regarding sprintf vs snprint I get this from "Aleksander Nabaglo"
>
> 1: Calculate needed buffer size,
> 2: Use assert: bug will not be hidden.
> int nsp=0;
>
> sprintf(buf, " ..... %n", /* args */ , &nsp);
> if(buf_size <= nsp) { assert(0 & " buf[] too short ");
> exit(SOME_ERROR_CODE);
>
> is that okay ?
No, it won't compile. Besides a buffer overrun has already triggered
undefined behaviour by the time the if statement is executed, so we
cannot rely on it's behaviour either.
> I also heard from someone that using assert() in code going to be
> shipped is a bad idea. All assert statement, before the delivery, must
> be removed.
It's poor programming to depend on assert for error checking. Assert is
therefore internal consistency verification during development. It's
always possible for a customer to compile your program with NDEBUG
defined, and if your program does error or validity checking with
assert, then it's rendered very fragile.
> Do you have some code for safe sprintf() ?
Why? It's easy enough to write your own. Here is it's description from
the Standard:
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.
Returns
3 The sprintf function returns the number of characters written in the
array, not counting the terminating null character, or a negative
value if an encoding error occurred.
>> But it seems from other stuff you've said that you're only interested
>> in Linux, which is fine,
>
> I actually thought snprint() will save me from buffer problems and now
> after a little search I can see that I was using it blindly.
As I said elsewhere, provided the second argument is indeed the size of
the first, then buffer overrun *will* be prevented, though data loss
will occur.
One solution is to use snprintf itself to determine the minimum size of
the buffer that will be required and use a sufficiently large one.
> Anyway, I
> still like the for( int i = 0;..) localization in C99. I don't like my
> programs to be polluted by some index numbers when I know I am on
> Linux for next decade, at least.
If your functions are relatively short then there won't be
much "pollution" as you call it. You could also introduce a block,
though that's a very ugly solution, IMO.
PS. "Knowing" things for as much as a decade in advance is very risky in
computing (not the theoretical side.) If I were you, I'd still try to
keep my routines as portable as possible if the costs are not too high.
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/5/2008 3:14:27 PM
|
|
Richard Heathfield <rjh@see.sig.invalid> writes:
<snip>
>>> No, it doesn't have to be silent, because you could be listening
>>> - but by the time you've taken the trouble to add the code to listen
>>> for data loss and take corrective action to ensure that no data loss
>>> occurs after all,
>>
>> Exactly.
>>
>>> you might as well have used sprintf in the first place.
>>
>> But the difference is that with sprintf you need to know this in
>> advance, while with snprintf you can "adapt as you go", so to speak.
>
> Mostly you do know in advance. On the rare occasions when you don't, it's
> generally easy enough to find out.
Generally, yes, but how do you find out how much storage you need for
%p? I don't know any reliable way.
<snip>
>>> Arbitrary data loss might be okay for some people, but it's something
>>> I try to avoid if I can.
Just as with strncpy there are rare times when snprintf is exactly
what you want. I once worked with a network event logging system that
gave you one packet to say what you wanted and truncation was the only
option. Life being what it is, that was before the snprintf family
had come into being, so I basically had to write it (simplified for
the cases that were needed) and I've never actually wanted this
truncation semantics since.
--
Ben.
|
|
0
|
|
|
|
Reply
|
ben.usenet (6515)
|
8/5/2008 3:42:14 PM
|
|
arnuld said:
>> On Tue, 05 Aug 2008 10:58:20 +0000, Richard Heathfield wrote:
>
>
>> Using snprintf does not guarantee this. You have to use it /properly/.
>> And if you use sprintf properly, you get the same safety. So snprintf
>> isn't actually all that big a deal.
>
> I searched the archives and really much confused. "Ben Pfaff" says:
>
> The point is that strncpy() is as dangerous
> as strcpy() if it isn't used with care.
He's right. Likewise, snprintf has its caveats and gotchas.
> and regarding sprintf vs snprint I get this from "Aleksander Nabaglo"
>
> 1: Calculate needed buffer size,
> 2: Use assert: bug will not be hidden.
> int nsp=0;
>
> sprintf(buf, " ..... %n", /* args */ , &nsp);
> if(buf_size <= nsp) { assert(0 & " buf[] too short ");
> exit(SOME_ERROR_CODE);
>
> is that okay ?
It's bizarre. The assert is meaningless, for a start. Secondly, if the idea
is to calculate whether a buffer overrun /has occurred/, then it's too
little too late. Instead:
1) find out how much data you need to store in your string;
2) allocate that much storage;
3) construct your string.
This is not exactly rocket science.
> I also heard from someone that using assert() in code going to be shipped
> is a bad idea. All assert statement, before the delivery, must be
> removed.
Assertions are best used for checking program assumptions. If you have an
assertion such as assert(foo > bar), what you're saying is "either foo is
greater than bar at this point, OR MY CODE IS WRONG". You never use
assertions to check the validity of data, only the validity of assumptions
you have made as a programmer. Since you obviously wouldn't dream of
shipping your code until you'd fixed all the bugs, there is no point in
leaving the assertions in place in the production code - so you can turn
them off by defining NDEBUG (which means you don't have to delete them
from the source code).
> Do you have some code for safe sprintf() ?
I have a safe /strategy/ for sprintf:
1) find out how much storage you need for the string;
2) allocate that much;
3) call sprintf to build the string.
>> But it seems from other stuff you've said that you're only interested in
>> Linux, which is fine,
>
> I actually thought snprint() will save me from buffer problems and now
> after a little search I can see that I was using it blindly.
You're not the first, and you won't be the last.
<snip>
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/5/2008 3:44:14 PM
|
|
Ben Bacarisse wrote:
> Richard Heathfield <rjh@see.sig.invalid> writes:
>
> <snip>
>>>> No, it doesn't have to be silent, because you could be listening
>>>> - but by the time you've taken the trouble to add the code to
>>>> listen for data loss and take corrective action to ensure that no
>>>> data loss occurs after all,
>>>
>>> Exactly.
>>>
>>>> you might as well have used sprintf in the first place.
>>>
>>> But the difference is that with sprintf you need to know this in
>>> advance, while with snprintf you can "adapt as you go", so to speak.
>>
>> Mostly you do know in advance. On the rare occasions when you don't,
>> it's generally easy enough to find out.
>
> Generally, yes, but how do you find out how much storage you need for
> %p? I don't know any reliable way.
char *str;
FILE *tmpf = tmpfile();
if (tmpf)
int n = fprintf(tmpf, "%p", (void*)ptr);
if (n < 0) /* error */
else str = malloc(n + 1);
if (str) /* use sprintf */
fclose(tmpf);
<snip>
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/5/2008 3:50:42 PM
|
|
Richard Heathfield <rjh@see.sig.invalid> writes:
> arnuld said:
<snip>
>> and regarding sprintf vs snprint I get this from "Aleksander Nabaglo"
>>
>> 1: Calculate needed buffer size,
>> 2: Use assert: bug will not be hidden.
>> int nsp=0;
>>
>> sprintf(buf, " ..... %n", /* args */ , &nsp);
>> if(buf_size <= nsp) { assert(0 & " buf[] too short ");
>> exit(SOME_ERROR_CODE);
>>
>> is that okay ?
>
> It's bizarre. The assert is meaningless, for a start. Secondly, if the idea
> is to calculate whether a buffer overrun /has occurred/, then it's too
> little too late.
It looks like the assert is there so that you don't get a *silent*
buffer overflow. The advice given is to calculate the size needed
*and* to check that you did not need more. So this assert is of the
right sort -- it checks internal program logic to spot, during
development, a logic error that might otherwise slip past.
--
Ben.
|
|
0
|
|
|
|
Reply
|
ben.usenet (6515)
|
8/5/2008 3:51:46 PM
|
|
santosh wrote:
> Ben Bacarisse wrote:
>
>> Richard Heathfield <rjh@see.sig.invalid> writes:
>>
>> <snip>
>>>>> No, it doesn't have to be silent, because you could be listening
>>>>> - but by the time you've taken the trouble to add the code to
>>>>> listen for data loss and take corrective action to ensure that no
>>>>> data loss occurs after all,
>>>>
>>>> Exactly.
>>>>
>>>>> you might as well have used sprintf in the first place.
>>>>
>>>> But the difference is that with sprintf you need to know this in
>>>> advance, while with snprintf you can "adapt as you go", so to
>>>> speak.
>>>
>>> Mostly you do know in advance. On the rare occasions when you don't,
>>> it's generally easy enough to find out.
>>
>> Generally, yes, but how do you find out how much storage you need for
>> %p? I don't know any reliable way.
>
> char *str;
> FILE *tmpf = tmpfile();
>
> if (tmpf)
> int n = fprintf(tmpf, "%p", (void*)ptr);
> if (n < 0) /* error */
> else str = malloc(n + 1);
>
> if (str) /* use sprintf */
> fclose(tmpf);
>
> <snip>
Oops sorry about all the syntax errors in that code.
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/5/2008 3:53:52 PM
|
|
Ben Bacarisse said:
<snip>
> how do you find out how much storage you need for
> %p? I don't know any reliable way.
If the implementation uses the same representation each time for a given
pointer value, then it can be done using tmpfile and fprintf (which, of
course, returns the number of characters written).
If the implementation is pathological, you can at least get the length of
*a* representation of a pointer by this method, and then you can read back
in the value you just wrote out.
<snip>
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/5/2008 3:53:54 PM
|
|
Ben Bacarisse said:
> Richard Heathfield <rjh@see.sig.invalid> writes:
>
>> arnuld said:
> <snip>
>>> and regarding sprintf vs snprint I get this from "Aleksander Nabaglo"
>>>
>>> 1: Calculate needed buffer size,
>>> 2: Use assert: bug will not be hidden.
>>> int nsp=0;
>>>
>>> sprintf(buf, " ..... %n", /* args */ , &nsp);
>>> if(buf_size <= nsp) { assert(0 & " buf[] too short ");
>>> exit(SOME_ERROR_CODE);
>>>
>>> is that okay ?
>>
>> It's bizarre. The assert is meaningless, for a start. Secondly, if the
>> idea is to calculate whether a buffer overrun /has occurred/, then it's
>> too little too late.
>
> It looks like the assert is there so that you don't get a *silent*
> buffer overflow.
Firstly, by the time the assertion happens (IF it happens), the overrun has
already occurred, and that's UB, so all bets are off.
Secondly, whether the buffer is big enough is very likely to be dependent
on runtime data, in which case an assertion is effectively being used for
data validation - never a good idea.
(Thirdly, the assertion might not happen at all, because NDEBUG might be
defined. Included only for completeness, since it's true of all
assertions.)
> The advice given is to calculate the size needed
> *and* to check that you did not need more. So this assert is of the
> right sort -- it checks internal program logic to spot, during
> development, a logic error that might otherwise slip past.
I see your point, and I'm prepared to meet it about halfway. It's still
broken code, IMHO. It's like having a safety net laid out flat on the
concrete.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/5/2008 4:23:08 PM
|
|
Richard Heathfield <rjh@see.sig.invalid> writes:
> Ben Bacarisse said:
>
>> Richard Heathfield <rjh@see.sig.invalid> writes:
>>
>>> arnuld said:
>> <snip>
>>>> and regarding sprintf vs snprint I get this from "Aleksander Nabaglo"
>>>>
>>>> 1: Calculate needed buffer size,
>>>> 2: Use assert: bug will not be hidden.
>>>> int nsp=0;
>>>>
>>>> sprintf(buf, " ..... %n", /* args */ , &nsp);
>>>> if(buf_size <= nsp) { assert(0 & " buf[] too short ");
>>>> exit(SOME_ERROR_CODE);
>>>>
>>>> is that okay ?
>>>
>>> It's bizarre. The assert is meaningless, for a start. Secondly, if the
>>> idea is to calculate whether a buffer overrun /has occurred/, then it's
>>> too little too late.
>>
>> It looks like the assert is there so that you don't get a *silent*
>> buffer overflow.
>
> Firstly, by the time the assertion happens (IF it happens), the overrun has
> already occurred, and that's UB, so all bets are off.
Don't be so pessimistic -- the great thing about UB is that it can't
get any worse! The assert can't make the program any less
well-defined UB, and there just the chance that something good happens
as if by magic.
> Secondly, whether the buffer is big enough is very likely to be dependent
> on runtime data, in which case an assertion is effectively being used for
> data validation - never a good idea.
I don't get this. They seem to be suggesting that the calculation
be checked via another route and that seems to be what assert is for,
surely? It would be clearer if the assert was for the condition they
test in the 'if', but...
> (Thirdly, the assertion might not happen at all, because NDEBUG might be
> defined. Included only for completeness, since it's true of all
> assertions.)
Which, I think, explains why the assert is written the way it is. The
author wants the exit to happen, even in production code. Now that is
odd, even to me, but all I am trying to do in see what the thinking was.
I'd either just assert(buf_size > nsp) or keep the "if" test and
replace the assert with an error message.
>> The advice given is to calculate the size needed
>> *and* to check that you did not need more. So this assert is of the
>> right sort -- it checks internal program logic to spot, during
>> development, a logic error that might otherwise slip past.
>
> I see your point, and I'm prepared to meet it about halfway. It's still
> broken code, IMHO. It's like having a safety net laid out flat on the
> concrete.
A better analogy would be a safety net over a hole in the floor.
The idea that it might catch you before you hit the basement.
--
Ben.
|
|
0
|
|
|
|
Reply
|
ben.usenet (6515)
|
8/5/2008 4:55:06 PM
|
|
arnuld wrote:
>
.... snip ...
>
> I actually thought snprint() will save me from buffer problems and
> now after a little search I can see that I was using it blindly.
> Anyway, I still like the for( int i = 0;..) localization in C99. I
> don't like my programs to be polluted by some index numbers when I
> know I am on Linux for next decade, at least.
Bear in mind that everything you have been told, or advised, here
has nothing to do with Linux. It applies to all C programs. The
only requirement is that the compiler meet the demands of the
standard, and most do (at least to the C90 standard). However most
also require care in usage to keep them compatible. Look at your
compiler manuals.
For gcc the essential steps are to run it with:
gcc -W -Wall -ansi -pedantic
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
|
|
0
|
|
|
|
Reply
|
cbfalconer (19183)
|
8/5/2008 6:04:43 PM
|
|
On Aug 4, 11:32=A0pm, arnuld <sunr...@invalid.address> wrote:
[snip]
> I also heard from someone that using assert() in code going to be shipped
> is a bad idea. All assert statement, before the delivery, must be removed=
..
Using assert() is strictly a debugging tool. The meaning of:
assert(foo);
is "I am absolutely sure that foo is true. I would be utterly
astonished if foo were *ever* false."
You cannot rely on assert() as a runtime correction to anything
because release builds typically #undef it. If you rely on assert()
to catch problems, the behavior can change when you recompile. And it
leaves a *very* bad impression when an assert() fires on a customer
site.
If you think that there is even a remote chance that boolean foo will
ever be false, then you need to do this:
if (foo)
perform_normal_stuff();
else
handle_panic_situation();
If you want to see a masterful use of assert [there are 1980 well done
asserts in the code], I highly recommend this chess program for study:
Look here:
http://arctrix.com/nas/chess/fruit/
Alternative here:
http://wbec-ridderkerk.nl/html/download.htm
[snip]
|
|
0
|
|
|
|
Reply
|
dcorbit (2696)
|
8/5/2008 7:11:48 PM
|
|
On 5 Aug 2008 at 18:04, CBFalconer wrote:
> For gcc the essential steps are to run it with:
>
> gcc -W -Wall -ansi -pedantic
Interesting. So you've silently dropped the extra flags that force gcc
to be non-conforming, despite swearing blind for post after post in a
recent thread that they didn't, in the face of clear evidence to the
contrary? At least be grown up enough to admit your mistakes.
|
|
0
|
|
|
|
Reply
|
nospam59 (9755)
|
8/5/2008 10:00:57 PM
|
|
In article <slrng9hjco.52l.nospam@nospam.invalid>,
Antoninus Twink <nospam@nospam.invalid> wrote:
>On 5 Aug 2008 at 18:04, CBFalconer wrote:
>> For gcc the essential steps are to run it with:
>>
>> gcc -W -Wall -ansi -pedantic
>
>Interesting. So you've silently dropped the extra flags that force gcc
>to be non-conforming, despite swearing blind for post after post in a
>recent thread that they didn't, in the face of clear evidence to the
>contrary? At least be grown up enough to admit your mistakes.
>
Grown up? CBF? What planet are you posting from?
Actually, in terms of physical (not mental) age, CBF is, I believe,
about as old as dirt.
|
|
0
|
|
|
|
Reply
|
gazelle2 (1306)
|
8/6/2008 12:34:34 AM
|
|
> On Tue, 05 Aug 2008 15:44:14 +0000, Richard Heathfield wrote:
> I have a safe /strategy/ for sprintf:
>
> 1) find out how much storage you need for the string;
> 2) allocate that much;
> 3) call sprintf to build the string.
you mean you missed the 4th step ;)
1) find out how much storage you need for the string
2) malloc() that much
3) call sprintf to build the string
4) don't forget to free() the memory
--
www.lispmachine.wordpress.com
my email is @ the above blog
check the "About Myself" page
|
|
0
|
|
|
|
Reply
|
sunrise2 (598)
|
8/6/2008 4:58:32 AM
|
|
> On Wed, 06 Aug 2008 06:24:59 +0000, Richard Heathfield wrote:
>> arnuld said:
>> you mean you missed the 4th step ;)
>>
>> 1) find out how much storage you need for the string
>> 2) malloc() that much
>> 3) call sprintf to build the string
>> 4) don't forget to free() the memory
> Only if you've allocated the memory dynamically, which isn't necessarily
> the case.
you mean I can simply do:
1) enum { ARRSIZE = 101 }
2) char array[ARRSIZE]
3) sprintf( ..... )
--
www.lispmachine.wordpress.com
my email is @ the above blog
check the "About Myself" page
|
|
0
|
|
|
|
Reply
|
sunrise2 (598)
|
8/6/2008 6:23:18 AM
|
|
arnuld said:
>> On Tue, 05 Aug 2008 15:44:14 +0000, Richard Heathfield wrote:
>
>> I have a safe /strategy/ for sprintf:
>>
>> 1) find out how much storage you need for the string;
>> 2) allocate that much;
>> 3) call sprintf to build the string.
>
>
> you mean you missed the 4th step ;)
>
> 1) find out how much storage you need for the string
> 2) malloc() that much
> 3) call sprintf to build the string
> 4) don't forget to free() the memory
Only if you've allocated the memory dynamically, which isn't necessarily
the case.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/6/2008 6:24:59 AM
|
|
arnuld wrote:
>> On Wed, 06 Aug 2008 06:24:59 +0000, Richard Heathfield wrote:
>
>>> arnuld said:
>>> you mean you missed the 4th step ;)
>>>
>>> 1) find out how much storage you need for the string
>>> 2) malloc() that much
>>> 3) call sprintf to build the string
>>> 4) don't forget to free() the memory
>
>
>> Only if you've allocated the memory dynamically, which isn't
>> necessarily the case.
>
>
> you mean I can simply do:
>
> 1) enum { ARRSIZE = 101 }
> 2) char array[ARRSIZE]
> 3) sprintf( ..... )
You can, but if array is not large enough a buffer overrun will occur,
while with snprintf you can prevent that at the cost of data loss.
An exercise: Consider the format specifier "%+0#*.*LG\t%0#p\n%ls\n"
How many characters does a buffer need to be to prevent a overrun? Can
you find out without using *printf function?
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/6/2008 6:45:14 AM
|
|
arnuld said:
>> On Wed, 06 Aug 2008 06:24:59 +0000, Richard Heathfield wrote:
>
>>> arnuld said:
>>> you mean you missed the 4th step ;)
>>>
>>> 1) find out how much storage you need for the string
>>> 2) malloc() that much
>>> 3) call sprintf to build the string
>>> 4) don't forget to free() the memory
>
>
>> Only if you've allocated the memory dynamically, which isn't necessarily
>> the case.
>
>
> you mean I can simply do:
>
> 1) enum { ARRSIZE = 101 }
> 2) char array[ARRSIZE]
> 3) sprintf( ..... )
I mean it depends on the circumstances. For example, if you want to
"sprint" three possibly-negative ints and a ten-byte string, separated by
spaces, you know at compile time that you need
3 * /* three */
((sizeof(int) * CHAR_BIT + 2) / 3) + /* ints, */
1) + /* possibly negative, */
10 + /* and a ten-byte string, */
3 + /* and three separating spaces, */
1 /* and a null terminator */
which is a constant integer expression and can be used as an array size. So
in this case, dynamic allocation is not required and thus no free() call
is necessary. But if, on the other hand, you wanted space for n ints, then
of course you would need to allocate dynamically.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/6/2008 6:53:05 AM
|
|
santosh said:
<snip>
> An exercise: Consider the format specifier "%+0#*.*LG\t%0#p\n%ls\n"
An exercise: Consider shooting the analyst. :-)
> How many characters does a buffer need to be to prevent a overrun?
No amount will be sufficient, since an overrun is always one possible
result of undefined behaviour - and that format specifier *will* invoke
undefined behaviour if you pass it to *printf.
> Can you find out without using *printf function?
Simply looking it up in the Standard was sufficient.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/6/2008 7:00:41 AM
|
|
> On Wed, 06 Aug 2008 06:53:05 +0000, Richard Heathfield wrote:
> I mean it depends on the circumstances. For example, if you want to
> "sprint" three possibly-negative ints and a ten-byte string, separated by
> spaces, you know at compile time that you need
>
> 3 * /* three */
> ((sizeof(int) * CHAR_BIT + 2) / 3) + /* ints, */
> 1) + /* possibly negative, */
> 10 + /* and a ten-byte string, */
> 3 + /* and three separating spaces, */
> 1 /* and a null terminator */
> ... SNIP..
I really did not understand the most of it ;) but I got the idea that you
must know your input size in advance which I already know. e.g if I am
sure that my input is no more than 10 bytes then:
char arrc[10];
sprintf(arrc, "This input is definitely more than 10 bytes");
what will it do. In curiosity I have played with this code:
#include <stdio.h>
int main( void )
{
char arrc[10];
sprintf(arrc, "This is more than 10 bytes, of course");
printf("-------------------------------\n");
printf("%s", arrc);
return 0;
}
=============== OUTPUT =================
[arnuld@dune ztest]$ gcc -std=c99 -pedantic -Wall -Wextra test.c
[arnuld@dune ztest]$ ./a.out
-------------------------------
Segmentation fault
[arnuld@dune ztest]$
Now if I add a '\n'
1.) after the %s in last printf.
2.) or in the end of the string literal (the 2nd argument to sprintf)
then the the output is this:
[arnuld@dune ztest]$ ./a.out
-------------------------------
This is more than 10 bytes, of course
Segmentation fault
[arnuld@dune ztest]$
It prints the message though Segfaults. I don't understand it.
--
www.lispmachine.wordpress.com
my email is @ the above blog
check the "About Myself" page
|
|
0
|
|
|
|
Reply
|
sunrise2 (598)
|
8/6/2008 7:38:19 AM
|
|
Richard Heathfield wrote:
> santosh said:
>
> <snip>
>
>> An exercise: Consider the format specifier "%+0#*.*LG\t%0#p\n%ls\n"
>
> An exercise: Consider shooting the analyst. :-)
>
>> How many characters does a buffer need to be to prevent a overrun?
>
> No amount will be sufficient, since an overrun is always one possible
> result of undefined behaviour - and that format specifier *will*
> invoke undefined behaviour if you pass it to *printf.
>
>> Can you find out without using *printf function?
>
> Simply looking it up in the Standard was sufficient.
Yes, it does seem rather silly. However barring the '0' and '#' before
the 'p' specifier, the rest is correct, and it emphasises my main
point, which is that with floating point values, it's not as easy to
pre-calculate the buffer size needed, as it is with integers. Of course
the 'p' specifier throws an additional spanner into the works.
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/6/2008 7:43:54 AM
|
|
arnuld wrote:
>> On Wed, 06 Aug 2008 06:53:05 +0000, Richard Heathfield wrote:
>
>
>> I mean it depends on the circumstances. For example, if you want to
>> "sprint" three possibly-negative ints and a ten-byte string,
>> separated by spaces, you know at compile time that you need
>>
>> 3 * /* three */
>> ((sizeof(int) * CHAR_BIT + 2) / 3) + /* ints, */
>> 1) + /* possibly negative, */
>> 10 + /* and a ten-byte string, */
>> 3 + /* and three separating
>> spaces, */
>> 1 /* and a null terminator */
>
>> ... SNIP..
>
>
> I really did not understand the most of it ;) but I got the idea that
> you must know your input size in advance which I already know. e.g if
> I am sure that my input is no more than 10 bytes then:
>
> char arrc[10];
> sprintf(arrc, "This input is definitely more than 10 bytes");
>
> what will it do. In curiosity I have played with this code:
<snip>
C doesn't say what happens after undefined behaviour is invoked. The
expected result could be derived, the program could crash, the machine
could crash, the fuses for your building's power supply could blow...
In short, there is not much point in experimenting with undefined
behaviour. It is of course nice to see what really happens on a buffer
overrun on your implementation, but undefined behaviour being what it
is, the same "thing" might not happen on the very next run of the same
program, or after the same program is recompiled with differring
options, or if it's run after a system upgrade, or with another
implementation on another machine etc.
Even if an instance of UB is defined and documented by your compiler,
there is no requirement that the next compiler define it or document
what it has defined or define it in a way that is compatible with the
previous compiler's behaviour and so on.
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/6/2008 7:50:36 AM
|
|
> On Wed, 06 Aug 2008 13:20:36 +0530, santosh wrote:
> C doesn't say what happens after undefined behaviour is invoked. The
> expected result could be derived, the program could crash, the machine
> could crash, the fuses for your building's power supply could blow...
>
> In short, there is not much point in experimenting with undefined
> behaviour.
> .. SNIP...
Now what is UB in this case. From this example i can see that sprintf does
not put any '\0' (NULL byte) in the end of the array while snprintf does.
--
www.lispmachine.wordpress.com
my email is @ the above blog
check the "About Myself" page
|
|
0
|
|
|
|
Reply
|
sunrise2 (598)
|
8/6/2008 8:00:12 AM
|
|
> On Wed, 06 Aug 2008 13:00:12 +0500, arnuld wrote:
> Now what is UB in this case. From this example i can see that sprintf does
> not put any '\0' (NULL byte) in the end of the array while snprintf does.
does it mean that I have to put /ARRSIZE - 1/ characters, keeping the last
for NULL byte ?
--
www.lispmachine.wordpress.com
my email is @ the above blog
check the "About Myself" page
|
|
0
|
|
|
|
Reply
|
sunrise2 (598)
|
8/6/2008 8:01:10 AM
|
|
arnuld wrote:
>> On Wed, 06 Aug 2008 13:20:36 +0530, santosh wrote:
>
>
>> C doesn't say what happens after undefined behaviour is invoked. The
>> expected result could be derived, the program could crash, the
>> machine could crash, the fuses for your building's power supply could
>> blow...
>>
>> In short, there is not much point in experimenting with undefined
>> behaviour.
>
>> .. SNIP...
>
>
> Now what is UB in this case.
The buffer overrun.
> From this example i can see that sprintf does not put any '\0' (NULL
> byte) in the end of the array while snprintf does.
Firstly NULL is a macro that expands to a null pointer constant. It is
not conceptually related to the null *character* , i.e., '\0'.
Secondly snprintf and sprintf both always terminate their output with a
null character. From which example do you claim that sprintf did not
put any '\0' byte at the end of the array, while snprintf did? If it
was from a program that invokes Undefined Behaviour then your
observations and conclusions are not valid.
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/6/2008 8:28:44 AM
|
|
arnuld wrote:
>> On Wed, 06 Aug 2008 13:00:12 +0500, arnuld wrote:
>
>> Now what is UB in this case. From this example i can see that sprintf
>> does not put any '\0' (NULL byte) in the end of the array while
>> snprintf does.
>
>
> does it mean that I have to put /ARRSIZE - 1/ characters, keeping the
> last for NULL byte ?
No. With snprintf N-1 characters will be written to a buffer of N
elements and then a null character will be added. With sprintf however
many characters that are generated by interpretation of the format
specifier and the subsequent arguments, if any, will be written and a
null character added at the end.
See the draft Standard for details. Search for n1256.pdf with Google.
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/6/2008 8:31:59 AM
|
|
arnuld said:
>> On Wed, 06 Aug 2008 06:53:05 +0000, Richard Heathfield wrote:
>
>
>> I mean it depends on the circumstances. For example, if you want to
>> "sprint" three possibly-negative ints and a ten-byte string, separated
>> by spaces, you know at compile time that you need
>>
>> 3 * /* three */
>> ((sizeof(int) * CHAR_BIT + 2) / 3) + /* ints, */
>> 1) + /* possibly negative, */
>> 10 + /* and a ten-byte string, */
>> 3 + /* and three separating spaces,
>> */
>> 1 /* and a null terminator */
>
>> ... SNIP..
>
>
> I really did not understand the most of it ;)
Then stick with snprintf.
In fact, stick with Visual Basic.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/6/2008 8:34:07 AM
|
|
santosh said:
<snip>
> However barring the '0' and '#' before
> the 'p' specifier, the rest is correct, and it emphasises my main
> point,
Really? I'd have thought the opposite was true.
> which is that with floating point values, it's not as easy to
> pre-calculate the buffer size needed, as it is with integers.
Sure it is. In general? No, perhaps not. But within a given problem domain,
it's normally not so bad as all that.
> 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.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/6/2008 8:37:53 AM
|
|
Richard Heathfield wrote:
> santosh said:
<snip>
>> 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.
The behaviour is implementation defined, and I doubt that it is
allowable for implementation defined behaviour to suddenly change
during runtime or compile-time. Such behaviour must be defined, known
to the programmer before-hand. It could only change during translation
or execution *if* the implementation provided a way to access the new
definition from within the program. This would increase program
complexity to such an extent that no one would then program in C. :-)
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/6/2008 8:45:47 AM
|
|
santosh wrote:
> Richard Heathfield wrote:
>> santosh said:
>
> <snip>
>
>>> 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.
>
> The behaviour is implementation defined, and I doubt that it is
> allowable for implementation defined behaviour to suddenly change
> during runtime or compile-time. Such behaviour must be defined, known
> to the programmer before-hand.
"If the current clock-time has an even number of seconds, display
this way; otherwise, display that (longer) way".
> It could only change during translation
> or execution *if* the implementation provided a way to access the new
> definition from within the program.
That's OK; the definition is the same at all times.
> This would increase program
> complexity to such an extent that no one would then program in C. :-)
No, it would reduce uptake of the willfully variable implementation
to such an extent that no one would them program on it -- or at least,
that part of it.
--
'It changed the future .. and it changed us.' /Babylon 5/
Hewlett-Packard Limited registered no:
registered office: Cain Road, Bracknell, Berks RG12 1HN 690597 England
|
|
0
|
|
|
|
Reply
|
chris.dollin (1683)
|
8/6/2008 9:00:34 AM
|
|
santosh said:
> Richard Heathfield wrote:
>> santosh said:
>
> <snip>
>
>>> 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.
>
> The behaviour is implementation defined, and I doubt that it is
> allowable for implementation defined behaviour to suddenly change
> during runtime or compile-time.
C&V, please.
> Such behaviour must be defined, known to the programmer before-hand.
Yes, but there's nothing in the Standard that says the behaviour can't
follow dynamic rules.
Case in point: I have compiler conformance documentation here that, under
"4.9.6.1 The output for %p conversion in fprintf", says: "In near data
models, four hex digits (XXXX). In far data models, four hex digits,
colon, four hex digits (XXXX:XXXX)."
So for that implementation we have two different definitions of behaviour,
depending on the invocation options. Note, too, that it doesn't say
anything about normalising the pointer, so we could certainly end up with
two different strings representing the same pointer, even within this
fairly limited excursion into the libertarian world of
implementation-defined behaviour. Given this as a starting point, it isn't
difficult to imagine conformance documentation that says something like
"the output for %p conversion in printf is a hash of the pointer bits and
the current time and various other system-dependent values, expressed as a
non-padded and arbitrarily long string of non-colon characters followed by
a colon and the address in decimal notation".
> It could only change during translation
> or execution *if* the implementation provided a way to access the new
> definition from within the program.
Or if the change was in accordance with some kind of dynamic rule.
> This would increase program
> complexity to such an extent that no one would then program in C. :-)
No, mostly we just pray for sane implementations. :-)
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/6/2008 9:05:32 AM
|
|
> On Wed, 06 Aug 2008 08:34:07 +0000, Richard Heathfield wrote:
> Then stick with snprintf.
:(
> In fact, stick with Visual Basic.
Richard....... no... I hate VB
--
www.lispmachine.wordpress.com
my email is @ the above blog
check the "About Myself" page
|
|
0
|
|
|
|
Reply
|
sunrise2 (598)
|
8/6/2008 9:07:30 AM
|
|
On 5 Aug, 16:44, Richard Heathfield <r...@see.sig.invalid> wrote:
[RCH doesn't seem to like snprintf()]
[I must admit its lack of portability puts me off]
<snip>
> I have a safe /strategy/ for sprintf:
>
> 1) find out how much storage you need for the string;
how?
If I do it by machine what's wrong with using snprintf()?
Internally it's probably using the same code as sprintf()
making it highly likely to get the same answer.
If I do it by hand then I have to recalculate it every time
I change machines (or compiler flags).
> 2) allocate that much;
> 3) call sprintf to build the string.
<snip>
--
Nick Keighley
> Infinitely many bits doesn't give you "100% accuracy". You will
> only be able to represent the algebraic numbers.
Sure, if you use one of those old-fashioned implementations that only
has aleph-null-bit floating-point. Any decent modern implementation
should provide at least aleph-one bits.
(Bill Pursell and Keith Thompson clc)
|
|
0
|
|
|
|
Reply
|
nick_keighley_nospam (4574)
|
8/6/2008 9:13:12 AM
|
|
>> santosh said:
>>> Of course the 'p' specifier throws an additional spanner into the
>>> works.
>Richard Heathfield wrote:
>> 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.
In article <g7bofi$jmr$1@registered.motzarella.org>
santosh <santosh.k83@gmail.com> wrote:
>The behaviour is implementation defined, and I doubt that it is
>allowable for implementation defined behaviour to suddenly change
>during runtime or compile-time.
In this case, "implementation-defined" simply means it must be
documented. It could be documented as "prints ten characters on
Mondays and five hundred characters on Fridays", for instance.
(Not very realistic, I admit, but pretty clearly permitted.)
>Such behaviour must be defined, known to the programmer
>before-hand.
Assuming, of course, that the programmer reads the implementation
document. If the goal is to write portable C, including porting
to future implementations, this becomes difficult. "Before I write
this, I need to read the documentation for a compiler that will
not be designed for another decade." :-)
In any case, to handle this with snprintf(), one might write, e.g.:
do {
need = snprintf(NULL, 0, fmt, arg1, arg2, ..., argN);
... handle error (need<0) case ...
result = snprintf(buf, size, fmt, arg1, arg2, ..., argN);
} while (result != need);
which is not guaranteed to terminate, but will not lose data. Or
more realistically, one could simply check whether result==need
after the second snprintf(), to make sure nothing important changed
(perhaps, e.g., one of the "arg"s mysteriously changed between the
two calls, which could happen in multithreaded code).
One can always make mistakes. The snprintf() function is no
protection against this. On the other hand, while no tool is ever
perfect, some tools are clearly better than others: sprintf() is
a useable tool, but snprintf() is a better one.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40�39.22'N, 111�50.29'W) +1 801 277 2603
email: gmail (figure it out) http://web.torek.net/torek/index.html
|
|
0
|
|
|
|
Reply
|
nospam252 (1722)
|
8/6/2008 9:18:38 AM
|
|
On Jul 19, 5:49 am, Ron Ford <r...@nowhere.net> wrote:
> I'm looking for a freeware c99 compiler for windows. I had intended to use
> MS's Visual C++ Express and use its C capability. In the past with my MS
> products, I've simply needed to make .c the filetype to invoke the C
> compiler. Here's a link
>
> http://www.microsoft.com/express/download/#webInstall
>
> The download is 2.6 megs, which is near a reasonable size for a compiler,
> but then setup.exe wants to download 87 megs of dot net framework hoggs
> that I don't want on my machine.
>
> In the past I've gone with Bloodshed, but I find myself unable to get the
> shell to stay open so I can see some output.
>
> The development environment for gcc is austere.
>
> Anyone have another suggestion?
In blood shed, using a getch() statement just before the return 0
statement in main function has worked for me. The shell stays open
(unless you enter some character) and you can see the output.
I think its not considered standard C but if seeing the output is the
only aim then nothing wrong with it I guess.
|
|
0
|
|
|
|
Reply
|
Broli00 (348)
|
8/6/2008 9:21:15 AM
|
|
Nick Keighley said:
> On 5 Aug, 16:44, Richard Heathfield <r...@see.sig.invalid> wrote:
>
> [RCH doesn't seem to like snprintf()]
That's at least the second time, so it's presumably not a typo, so I'm
moved to ask where you get the C from, in RCH?
> [I must admit its lack of portability puts me off]
Right. And that's the whole thing. When I *know* snprintf will be available
with portable semantics on all my target platforms, I will happily use it.
Until then, why pollute my code unnecessarily with non-portable stuff?
> <snip>
>
>> I have a safe /strategy/ for sprintf:
>>
>> 1) find out how much storage you need for the string;
>
> how?
Depends.
> If I do it by machine what's wrong with using snprintf()?
What if you haven't /got/ snprintf?
> Internally it's probably using the same code as sprintf()
> making it highly likely to get the same answer.
> If I do it by hand then I have to recalculate it every time
> I change machines (or compiler flags).
I've given an example elsethread of how simple examples can be calculated
at compile time. More complicated examples are, necessarily, more
complicated.
<snip>
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/6/2008 9:27:57 AM
|
|
Chris Dollin wrote:
> santosh wrote:
>
>> Richard Heathfield wrote:
>>> santosh said:
>>
>> <snip>
>>
>>>> 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.
>>
>> The behaviour is implementation defined, and I doubt that it is
>> allowable for implementation defined behaviour to suddenly change
>> during runtime or compile-time. Such behaviour must be defined, known
>> to the programmer before-hand.
>
> "If the current clock-time has an even number of seconds, display
> this way; otherwise, display that (longer) way".
But since all possible ways are specified, it okay, albeit less than
ideal. One can test the time for even seconds and adapt as necessary.
However this is not the case with the output for 'p' specifier changing
from invocation to invocation. Being implementation defined, it can
only change from one implementation to another. If it must change
during runtime, then all possibilities have to be defined and
documented.
For example this could be one possible definition of the format of
output produced by the 'p' specifier:
* The output generated for the p specifier is identical to the output
that would be generated if the void* value were cast to unsigned long
and printed with the '#lx' specifier.
If p's behaviour must vary during runtime then similar definitions
should be documented for each such instance. Simply varying in an
undefined manner is not implementation defined behaviour.
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/6/2008 9:28:06 AM
|
|
Richard Heathfield wrote:
> santosh said:
>
>> Richard Heathfield wrote:
>>> santosh said:
>>
>> <snip>
>>
>>>> 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.
>>
>> The behaviour is implementation defined, and I doubt that it is
>> allowable for implementation defined behaviour to suddenly change
>> during runtime or compile-time.
>
> C&V, please.
The definition for implementation defined behaviour in section 3.4 of
n1256, taken in conjunction with the definition for unspecified
behaviour, on which it depends, seems to state pretty strongly that
_all_ the details of an instance of implementation defined behaviour
must be specified.
>> Such behaviour must be defined, known to the programmer before-hand.
>
> Yes, but there's nothing in the Standard that says the behaviour can't
> follow dynamic rules.
>
> Case in point: I have compiler conformance documentation here that,
> under "4.9.6.1 The output for %p conversion in fprintf", says: "In
> near data models, four hex digits (XXXX). In far data models, four hex
> digits, colon, four hex digits (XXXX:XXXX)."
This is fine, as far as I can see, since all possibilities are
specified. Thus one can program appropriately depending on the type of
the pointer.
<snip>
> Given this as a
> starting point, it isn't difficult to imagine conformance
> documentation that says something like "the output for %p conversion
> in printf is a hash of the pointer bits and the current time and
> various other system-dependent values, expressed as a non-padded and
> arbitrarily long string of non-colon characters followed by a colon
> and the address in decimal notation".
This *is* problematic since the exact hash method used is not specified,
even assuming that cross references do tell us the output formats of
the time and system dependent functions.
So this is a case where an instance of implementation defined behaviour
is not defined in a sufficiently useful manner. I suppose it's a QoI
issue, at least in this instance.
>> It could only change during translation
>> or execution *if* the implementation provided a way to access the new
>> definition from within the program.
>
> Or if the change was in accordance with some kind of dynamic rule.
Yes, in which case those dynamic rules must be specified.
I think the intent behind implementation defined behaviour is that
conforming implementations define it to a sufficiently precise and
useful level. Otherwise the Standard could just as well have classified
them under undefined behaviour.
>> This would increase program
>> complexity to such an extent that no one would then program in C. :-)
>
> No, mostly we just pray for sane implementations. :-)
Right. I suppose that we should perhaps be glad that the comp.lang.c
regulars aren't implementors too, or the DS9K would actually exist. :-)
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/6/2008 9:45:48 AM
|
|
pereges wrote:
<snip>
> In blood shed, using a getch() statement just before the return 0
> statement in main function has worked for me. The shell stays open
> (unless you enter some character) and you can see the output.
>
> I think its not considered standard C but if seeing the output is the
> only aim then nothing wrong with it I guess.
What's wrong with:
getchar();
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/6/2008 9:52:50 AM
|
|
> On Wed, 06 Aug 2008 14:01:59 +0530, santosh wrote:
> No. With snprintf N-1 characters will be written to a buffer of N
> elements and then a null character will be added. With sprintf however
> many characters that are generated by interpretation of the format
> specifier and the subsequent arguments, if any, will be written and a
> null character added at the end.
so, for both sprintf and snprintf, the character count must be N-1,
reserving the last character for null.
> See the draft Standard for details. Search for n1256.pdf with Google.
I downloaded it, 3.6 MB ,went straight to section 7.19.6.6 for sprintf.
Sadly after reading it and experimenting with both, I am no longer happier
at using snprintf as a replacement, in my specific case, as I already know
the maximum number of characters to be written.
--
www.lispmachine.wordpress.com
my email is @ the above blog
check the "About Myself" page
|
|
0
|
|
|
|
Reply
|
sunrise2 (598)
|
8/6/2008 10:00:30 AM
|
|
arnuld wrote:
>> On Wed, 06 Aug 2008 14:01:59 +0530, santosh wrote:
>>
>> No. With snprintf N-1 characters will be written to a buffer of N
>> elements and then a null character will be added. With sprintf
>> however many characters that are generated by interpretation of the
>> format specifier and the subsequent arguments, if any, will be
>> written and a null character added at the end.
>
> so, for both sprintf and snprintf, the character count must be N-1,
> reserving the last character for null.
Yes.
>> See the draft Standard for details. Search for n1256.pdf with Google.
>
> I downloaded it, 3.6 MB ,went straight to section 7.19.6.6 for
> sprintf. Sadly after reading it and experimenting with both, I am no
> longer happier at using snprintf as a replacement, in my specific
> case, as I already know the maximum number of characters to be
> written.
In this case sprintf is fine and more portable too, though I suppose it
wouldn't matter for your case.
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/6/2008 10:14:24 AM
|
|
On 6 Aug, 10:27, Richard Heathfield <r...@see.sig.invalid> wrote:
> Nick Keighley said:
> > On 5 Aug, 16:44, Richard Heathfield <r...@see.sig.invalid> wrote:
>
> > [RCH doesn't seem to like snprintf()]
>
> That's at least the second time, so it's presumably not a typo, so I'm
> moved to ask where you get the C from, in RCH?
er... I used to work with someone with those initials who was also
called Richard... oops.
> > [I must admit its lack of portability puts me off]
>
> Right. And that's the whole thing. When I *know* snprintf will be available
> with portable semantics on all my target platforms, I will happily use it.
> Until then, why pollute my code unnecessarily with non-portable stuff?
I believe there are versions Out There written in C90.
But that probably destroys my "it uses the same code" argument
<snip>
--
Nick Keighley
|
|
0
|
|
|
|
Reply
|
nick_keighley_nospam (4574)
|
8/6/2008 10:45:48 AM
|
|
santosh said:
<snip>
> The definition for implementation defined behaviour in section 3.4 of
> n1256, taken in conjunction with the definition for unspecified
> behaviour, on which it depends, seems to state pretty strongly that
> _all_ the details of an instance of implementation defined behaviour
> must be specified.
Fine, but that doesn't mean they can't be rule-based, as long as the rules
are fully specified.
>
>>> Such behaviour must be defined, known to the programmer before-hand.
>>
>> Yes, but there's nothing in the Standard that says the behaviour can't
>> follow dynamic rules.
>>
>> Case in point: I have compiler conformance documentation here that,
>> under "4.9.6.1 The output for %p conversion in fprintf", says: "In
>> near data models, four hex digits (XXXX). In far data models, four hex
>> digits, colon, four hex digits (XXXX:XXXX)."
>
> This is fine, as far as I can see, since all possibilities are
> specified. Thus one can program appropriately depending on the type of
> the pointer.
Not in ISO C, you can't, because in ISO C you can't assume you're using a
"near data model", and you can't assume you're using a "far data model",
because you might not even be using that kind of memory organisation at
all. What's more, even if you know you are, how are you going to
determine, using only the guarantees available to you in the ISO C
Standard, precisely which kind of "data model" you are using on a given
execution of the code?
> <snip>
>
>> Given this as a
>> starting point, it isn't difficult to imagine conformance
>> documentation that says something like "the output for %p conversion
>> in printf is a hash of the pointer bits and the current time and
>> various other system-dependent values, expressed as a non-padded and
>> arbitrarily long string of non-colon characters followed by a colon
>> and the address in decimal notation".
>
> This *is* problematic since the exact hash method used is not specified,
Bear in mind that even the conformance docs I showed you - which are from a
commercial implementation - were very vague about details like what the
bit before the colon represented, and what the bit after the colon
represented. So programmers aren't necessarily going to get as much
information from the conformance docs as you might like them to have. But
let's just say that we /do/ specify the exact hash method, and let's just
say that it's a weird one that might result in a hash of a few bytes (and
normally does) but might occasionally result in a hash of a few megabytes.
That really messes us up for %p, doesn't it?
> even assuming that cross references do tell us the output formats of
> the time and system dependent functions.
>
> So this is a case where an instance of implementation defined behaviour
> is not defined in a sufficiently useful manner. I suppose it's a QoI
> issue, at least in this instance.
Yeah, and that's the trouble - you are relying on QoI rather than on what
the Standard guarantees. And we have already seen that QoI isn't always as
Q as we might like it to be, even for some relatively popular flavours of
I.
>>> It could only change during translation
>>> or execution *if* the implementation provided a way to access the new
>>> definition from within the program.
>>
>> Or if the change was in accordance with some kind of dynamic rule.
>
> Yes, in which case those dynamic rules must be specified.
Yes, but that still gives you the problem that successive calls to *printf
might give wildly varying results for the number of characters needed to
represent %p.
> I think the intent behind implementation defined behaviour is that
> conforming implementations define it to a sufficiently precise and
> useful level.
What you and I think isn't really all that important compared to what the
Standard actually says.
> Otherwise the Standard could just as well have classified
> them under undefined behaviour.
In a sense, implementation-defined behaviour /is/ undefined (but only in a
sense). Consider C99's weasel words about main(), for example. If a C99
implementation defines void main, then void main is implementation-defined
- ON THAT IMPLEMENTATION. On other implementations, it remains undefined.
This isn't true for everything, obviously. We've pretty much got UCHAR_MAX
nailed down, for example. But for something as nebulous as %p, it's a real
problem.
>>> This would increase program
>>> complexity to such an extent that no one would then program in C. :-)
>>
>> No, mostly we just pray for sane implementations. :-)
>
> Right. I suppose that we should perhaps be glad that the comp.lang.c
> regulars aren't implementors too, or the DS9K would actually exist. :-)
The idea has been discussed before. Personally, I think it would be a
valuable teaching tool - even /without/ the optional hardware add-ons.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/6/2008 10:48:20 AM
|
|
santosh said:
> pereges wrote:
>
> <snip>
>
>> In blood shed, using a getch() statement just before the return 0
>> statement in main function has worked for me. The shell stays open
>> (unless you enter some character) and you can see the output.
>>
>> I think its not considered standard C but if seeing the output is the
>> only aim then nothing wrong with it I guess.
>
> What's wrong with:
>
> getchar();
What's wrong with:
open a shell, find the program, run the program from the shell.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/6/2008 10:49:03 AM
|
|
Richard Heathfield wrote:
> santosh said:
>
>> pereges wrote:
>>
>> <snip>
>>
>>> In blood shed, using a getch() statement just before the return 0
>>> statement in main function has worked for me. The shell stays open
>>> (unless you enter some character) and you can see the output.
>>>
>>> I think its not considered standard C but if seeing the output is
>>> the only aim then nothing wrong with it I guess.
>>
>> What's wrong with:
>>
>> getchar();
>
> What's wrong with:
>
> open a shell, find the program, run the program from the shell.
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.
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/6/2008 11:45:52 AM
|
|
Richard Heathfield wrote:
> santosh said:
>
> <snip>
>
>> The definition for implementation defined behaviour in section 3.4 of
>> n1256, taken in conjunction with the definition for unspecified
>> behaviour, on which it depends, seems to state pretty strongly that
>> _all_ the details of an instance of implementation defined behaviour
>> must be specified.
>
> Fine, but that doesn't mean they can't be rule-based, as long as the
> rules are fully specified.
In fact the Standard seems, (at a second glance), to be far more
restrictive that what I said above. I'll take the liberty of including
the relevant citations from n1256.
3.4.4
1 unspecified behavior
use of an unspecified value, or other behavior where this
International Standard provides two or more possibilities and imposes
no further requirements on which is chosen in any instance
3.4.1
1 implementation-defined behavior
unspecified behavior where each implementation documents how the
choice is made
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, and from this list
only, though the choice needn't be documented. And implementation
defined behaviour is merely a subset of unspecified behaviour where the
implementation's choice needs to be documented.
In light of this interpretation (though I'm sure I've overlooked
something important somewhere), how can the Standard specify the output
of the 'p' conversion specifier as implementation defined if it has not
itself defined the possible forms of that behaviour a conforming
implementation is required to select one from and document it?
<snip>
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/6/2008 12:10:44 PM
|
|
arnuld wrote:
>
.... snip ...
>
> Now what is UB in this case. From this example i can see that
> sprintf does not put any '\0' (NULL byte) in the end of the array
> while snprintf does.
Not so. From the standard:
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.
Returns
[#3] The sprintf function returns the number of characters
written in the array, not counting the terminating null
character, or a negative value if an encoding error
occurred.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
|
|
0
|
|
|
|
Reply
|
cbfalconer (19183)
|
8/6/2008 12:11:40 PM
|
|
Richard Heathfield wrote:
> arnuld said:
>
.... snip ...
>
>> I really did not understand the most of it ;)
>
> Then stick with snprintf. In fact, stick with Visual Basic.
Now that is unnecessary nasty treatment of a newbie.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
|
|
0
|
|
|
|
Reply
|
cbfalconer (19183)
|
8/6/2008 12:14:55 PM
|
|
Nick Keighley wrote:
> Richard Heathfield <r...@see.sig.invalid> wrote:
>
> [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.
>
> <snip>
>
>> I have a safe /strategy/ for sprintf:
>>
>> 1) find out how much storage you need for the string;
>
> how?
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.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
|
|
0
|
|
|
|
Reply
|
cbfalconer (19183)
|
8/6/2008 12:22:33 PM
|
|
santosh wrote:
> Richard Heathfield wrote:
>
.... snip ...
>
>> open a shell, find the program, run the program from the shell.
>
> 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.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
|
|
0
|
|
|
|
Reply
|
cbfalconer (19183)
|
8/6/2008 1:10:53 PM
|
|
santosh said:
> Richard Heathfield wrote:
>> santosh said:
>>
>> <snip>
>>
>>> The definition for implementation defined behaviour in section 3.4 of
>>> n1256, taken in conjunction with the definition for unspecified
>>> behaviour, on which it depends, seems to state pretty strongly that
>>> _all_ the details of an instance of implementation defined behaviour
>>> must be specified.
>>
>> Fine, but that doesn't mean they can't be rule-based, as long as the
>> rules are fully specified.
>
> In fact the Standard seems, (at a second glance), to be far more
> restrictive that what I said above.
In theory, perhaps. But at /my/ second glance, it appears far /less/
restrictive in /practice/.
> I'll take the liberty of including
> the relevant citations from n1256.
I'll buy that, given the snprintf context. :-)
>
> 3.4.4
> 1 unspecified behavior
> use of an unspecified value, or other behavior where this
> International Standard provides two or more possibilities and imposes
> no further requirements on which is chosen in any instance
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.
>
> 3.4.1
> 1 implementation-defined behavior
> unspecified behavior where each implementation documents how the
> choice is made
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. 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". 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).
> 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").
<snip>
> 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>
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/6/2008 2:14:52 PM
|
|
CBFalconer wrote:
> santosh wrote:
>> Richard Heathfield wrote:
>>
> ... snip ...
>>
>>> open a shell, find the program, run the program from the shell.
>>
>> 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.
Perhaps, but teaching him to open a shell is off-topic for this group,
as is getch(), hence the advise to use getchar().
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/6/2008 3:19:08 PM
|
|
CBFalconer said:
> Nick Keighley wrote:
>> Richard Heathfield <r...@see.sig.invalid> wrote:
>>
>> [RCH doesn't seem to like snprintf()]
>> [I must admit its lack of portability puts me off]
>
> What's non-portable?
Programs that rely on the existence and semantics of snprintf.
> It is specified in the C99 standard.
Non sequitur.
<snip>
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/6/2008 3:36:27 PM
|
|
In article <g7cfdc$quv$2@registered.motzarella.org>,
santosh <santosh.k83@gmail.com> wrote:
>CBFalconer wrote:
>
>> santosh wrote:
>>> Richard Heathfield wrote:
>>>
>> ... snip ...
>>>
>>>> open a shell, find the program, run the program from the shell.
>>>
>>> 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.
>
>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.)
|
|
0
|
|
|
|
Reply
|
gazelle2 (1306)
|
8/6/2008 4:17:16 PM
|
|
Richard Heathfield <rjh@see.sig.invalid> writes:
> 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.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
kst-u (21467)
|
8/6/2008 4:28:11 PM
|
|
Richard Heathfield wrote:
> santosh said:
<snip>
>> 3.4.4
>> 1 unspecified behavior
>> use of an unspecified value, or other behavior where this
>> International Standard provides two or more possibilities and
>> imposes no further requirements on which is chosen in any instance
>
> 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.
>> 3.4.1
>> 1 implementation-defined behavior
>> unspecified behavior where each implementation documents how the
>> choice is made
>
> 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.
> <snip>
>
>> 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?
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/6/2008 4:33:53 PM
|
|
Richard Heathfield <rjh@see.sig.invalid> writes:
> santosh said:
>> pereges wrote:
>>
>> <snip>
>>
>>> In blood shed, using a getch() statement just before the return 0
>>> statement in main function has worked for me. The shell stays open
>>> (unless you enter some character) and you can see the output.
>>>
>>> I think its not considered standard C but if seeing the output is the
>>> only aim then nothing wrong with it I guess.
>>
>> What's wrong with:
>>
>> getchar();
>
> 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.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
kst-u (21467)
|
8/6/2008 4:35:56 PM
|
|
santosh <santosh.k83@gmail.com> writes:
> 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.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
kst-u (21467)
|
8/6/2008 5:02:10 PM
|
|
Keith Thompson said:
<snip>
> There's no portable way to determine the maximum length of the result
> of a "%p" *printf conversion.
Right.
> 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.
Right.
> Even if you're
> given an even bigger string on the second attempt, the consequences
> are still no worse than a truncated result.
Right.
> 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.
> 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.
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.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/6/2008 5:31:40 PM
|
|
santosh said:
<snip>
> 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.
Right.
<snip>
> 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.
Right.
>> 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?
In this case, yes, because the thingy has to be an integer constant. But
don't deduce a general rule from this.
>> 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.
Yes. Of course, the rules might allow for considerable (but fully
documented) runtime freedom.
> 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?
Yes, provided that other constraints (small c) don't interfere (as with
UINT_MAX, which has to be a /constant/ throughout the translation and
execution of the program).
<snip>
> 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?),
Small c. Just plain vanilla Chambers dictionary constraints, not ISO/IEC
9899 "oh look, we just defined a word to have a new meaning" Constraints
with a big C.
> which when applied
> to the construct yield N possible behaviours?
Well, you can have ONE rule that gives MANY possible behaviours. But
speaking a little more broadly, yes, you're basically right.
<snip>
> But the forms of behaviour must be derivable, or otherwise, it would be
> undefined.
Yes. For example, if the implementation documents that it precedes the nth
instance of %p output with Fib(n) spaces, well, you could actually derive
that, couldn't you? (It might take a little work, but it is possible.)
>
> 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?
That's easy - the implementor can simply say, "I do %p like this", and
'this' can be as simple or as complicated as he wants, as long as he's
consistent.
<snip>
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/6/2008 5:43:43 PM
|
|
Keith Thompson wrote:
>
.... 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.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
|
|
0
|
|
|
|
Reply
|
cbfalconer (19183)
|
8/6/2008 7:47:25 PM
|
|
Richard Heathfield <rjh@see.sig.invalid> writes:
> 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.
>> 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.
>
> 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.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
kst-u (21467)
|
8/6/2008 8:12:29 PM
|
|
>Richard Heathfield <rjh@see.sig.invalid> writes:
>> 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.
In article <lnmyjp6gya.fsf@nuthaus.mib.org>
Keith Thompson <kst-u@mib.org> wrote:
>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.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40�39.22'N, 111�50.29'W) +1 801 277 2603
email: gmail (figure it out) http://web.torek.net/torek/index.html
|
|
0
|
|
|
|
Reply
|
nospam252 (1722)
|
8/6/2008 8:56:01 PM
|
|
On Aug 6, 12:31 pm, Richard Heathfield <rjh@see.sig.invalid> wrote:
> Keith Thompson said:
>
> <snip>
>
> > There's no portable way to determine the maximum length of the result
> > of a "%p" *printf conversion.
>
> Right.
>
> > 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.
>
> Right.
>
> > Even if you're
> > given an even bigger string on the second attempt, the consequences
> > are still no worse than a truncated result.
>
> Right.
>
> > 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.
>
> > 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.
>
> 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
|
|
0
|
|
|
|
Reply
|
s0suk3 (372)
|
8/6/2008 9:02:35 PM
|
|
CBFalconer <cbfalconer@yahoo.com> writes:
> Keith Thompson wrote:
> ... 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.
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.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
kst-u (21467)
|
8/6/2008 9:35:16 PM
|
|
On Wed, 06 Aug 2008 08:22:33 -0400,
CBFalconer <cbfalconer@yahoo.com> wrote:
> Nick Keighley wrote:
>> Richard Heathfield <r...@see.sig.invalid> wrote:
>>
>> [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.
>>
>> <snip>
>>
>>> I have a safe /strategy/ for sprintf:
^^^^^^^
>>>
>>> 1) find out how much storage you need for the string;
>>
>> how?
>
> 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
--
|
Martien Verbruggen | We are born naked, wet and hungry. Then
| things get worse.
|
|
|
0
|
|
|
|
Reply
|
mgjv (156)
|
8/6/2008 11:11:18 PM
|
|
Keith Thompson wrote:
> CBFalconer <cbfalconer@yahoo.com> writes:
>> Keith Thompson wrote:
>>
>> ... snip ...
>>>
>>> There's no portable way to determine the maximum length of the
>>> result of a "%p" *printf conversion.
>>>
.... 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.
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.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
|
|
0
|
|
|
|
Reply
|
cbfalconer (19183)
|
8/7/2008 1:59:48 AM
|
|
Martien Verbruggen wrote:
> CBFalconer <cbfalconer@yahoo.com> wrote:
>> Nick Keighley wrote:
>>> Richard Heathfield <r...@see.sig.invalid> wrote:
>>>
.... snip ...
>>>
>>>> 1) find out how much storage you need for the string;
>>>
>>> how?
>>
>> 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.
You can always replace the second call to snprintf with a call to
sprintf. The method answers Mr Keighleys 'how' response.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
|
|
0
|
|
|
|
Reply
|
cbfalconer (19183)
|
8/7/2008 2:07:00 AM
|
|
CBFalconer <cbfalconer@yahoo.com> writes:
> Keith Thompson wrote:
>> CBFalconer <cbfalconer@yahoo.com> writes:
>>> Keith Thompson wrote:
>>>
>>> ... snip ...
>>>>
>>>> There's no portable way to determine the maximum length of the
>>>> result of a "%p" *printf conversion.
>>>>
> ... 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.
>
> 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.
First off, a conforming implementation could, for example, say that
the "%p" conversion yields a random number of underscores followed by
the pointer representation in hexadecimal. *scanf would just ignore
the underscores. This would be a silly implementation, but I believe
it would be conforming.
Second, even assuming that each pointer value is converted to one and
only one string, what I meant was that there's no way to determine the
maximum length of the result of the "%p" conversion *over all possible
pointer values*.
Given the values of INT_MIN and INT_MAX, we can compute the maximum
length of the result of a "%d" conversion. No such computation is
possible for "%p".
In practice, there's (almost?) always an easily determined maximum
*for each implementation*.
But in the most general case, there's no value of N for which this:
char *foo(void *p)
{
static char buf[N];
sprintf(buf, "%p", p);
return buf;
}
can be guaranteed not to overflow buf.
Which is part of the reason that snprintf (if it's available) is so
useful: it at least lets you limit the consequences of guessing wrong
to truncation rather than undefined behavior.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
kst-u (21467)
|
8/7/2008 3:46:50 AM
|
|
CBFalconer wrote:
> Martien Verbruggen wrote:
>> CBFalconer <cbfalconer@yahoo.com> wrote:
>>> Nick Keighley wrote:
>>>> Richard Heathfield <r...@see.sig.invalid> wrote:
>>>>
> ... snip ...
>>>>
>>>>> 1) find out how much storage you need for the string;
>>>>
>>>> how?
>>>
>>> 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.
>
> 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.
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/7/2008 6:47:44 AM
|
|
santosh said:
<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.)
Right.
> 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.
That's about the only way I can think of for %p - it's normally a lot
simpler for other types.
> 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.
Very true. There might not even /be/ a filesystem - C doesn't mandate one -
in which case tmpfile might not even be supplied as a standard library
function (i.e. we might be dealing with a freestanding implementation).
> Using snprintf avoids this problem.
No, snprintf *doesn't* avoid the problem if, as you yourself say, "snprintf
is not available for use, for one reason or another", any more than a pet
dragon avoids the problem of lighting a campfire on a rainy day if the
dragon doesn't exist (or is otherwise occupied).
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/7/2008 7:05:08 AM
|
|
santosh wrote:
> CBFalconer wrote:
>
.... snip ...
>
>> 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.
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.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
|
|
0
|
|
|
|
Reply
|
cbfalconer (19183)
|
8/7/2008 7:49:39 AM
|
|
CBFalconer said:
> santosh wrote:
>> CBFalconer wrote:
>>
> ... snip ...
>>
>>> 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.
>
> In that case I suggest using the %n feature in the format string.
How does that improve matters?
>
> 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.
Fine, but a bit too late by then if you're relying on %n to tell you how
much memory you should have allocated.
<snip>
> It may be that %n is not available in C90.
It is available in C90.
> If so the above is hogwash.
I think it's hogwash anyway. :-) But perhaps I've missed your point.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/7/2008 8:35:18 AM
|
|
CBFalconer wrote:
> santosh wrote:
>> CBFalconer wrote:
>>
> ... snip ...
>>
>>> 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.
>
> 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.
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/7/2008 8:39:39 AM
|
|
On Aug 6, 4:02 pm, s0s...@gmail.com wrote:
> On Aug 6, 12:31 pm, Richard Heathfield <r...@see.sig.invalid> wrote:
>
>
>
> > Keith Thompson said:
>
> > <snip>
>
> > > There's no portable way to determine the maximum length of the result
> > > of a "%p" *printf conversion.
>
> > Right.
>
> > > 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.
>
> > Right.
>
> > > Even if you're
> > > given an even bigger string on the second attempt, the consequences
> > > are still no worse than a truncated result.
>
> > Right.
>
> > > 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.
>
> > > 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.
>
> > 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;
> }
>
> ...
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
|
|
0
|
|
|
|
Reply
|
s0suk3 (372)
|
8/7/2008 10:36:31 AM
|
|
s0suk3@gmail.com wrote:
<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);
That should be:
snprintf(service, serviceLen+1, "%d", port);
or the last character will be discarded.
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/7/2008 10:42:53 AM
|
|
s0suk3@gmail.com 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);
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/7/2008 10:53:48 AM
|
|
On Aug 7, 1:53 pm, Richard Heathfield <r...@see.sig.invalid> wrote:
> s0s...@gmail.com 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)
|
|
0
|
|
|
|
Reply
|
vippstar (1211)
|
8/7/2008 11:04:49 AM
|
|
On Aug 7, 5:42 am, santosh <santosh....@gmail.com> wrote:
> s0s...@gmail.com wrote:
>
> <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);
>
> That should be:
>
> snprintf(service, serviceLen+1, "%d", port);
>
> or the last character will be discarded.
Right! Thanks.
Sebastian
|
|
0
|
|
|
|
Reply
|
s0suk3 (372)
|
8/7/2008 11:08:32 AM
|
|
On Aug 7, 5:53 am, Richard Heathfield <r...@see.sig.invalid> wrote:
> s0s...@gmail.com 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);
>
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
|
|
0
|
|
|
|
Reply
|
s0suk3 (372)
|
8/7/2008 11:11:22 AM
|
|
vippstar@gmail.com said:
> On Aug 7, 1:53 pm, Richard Heathfield <r...@see.sig.invalid> wrote:
>> s0s...@gmail.com 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.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/7/2008 11:14:39 AM
|
|
vippstar@gmail.com writes:
> On Aug 7, 1:53 pm, Richard Heathfield <r...@see.sig.invalid> wrote:
>> s0s...@gmail.com 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. 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.
--
Ben.
|
|
0
|
|
|
|
Reply
|
ben.usenet (6515)
|
8/7/2008 11:20:26 AM
|
|
s0suk3@gmail.com wrote:
> On Aug 7, 5:53 am, Richard Heathfield <r...@see.sig.invalid> wrote:
>> s0s...@gmail.com 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);
>>
>
> 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.
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/7/2008 11:23:08 AM
|
|
Richard Heathfield wrote:
> vippstar@gmail.com said:
>
>> On Aug 7, 1:53 pm, Richard Heathfield <r...@see.sig.invalid> wrote:
>>> s0s...@gmail.com 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.
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/7/2008 11:24:56 AM
|
|
santosh wrote:
> Richard Heathfield wrote:
>
>> vippstar@gmail.com said:
>>
>>> On Aug 7, 1:53 pm, Richard Heathfield <r...@see.sig.invalid> wrote:
>>>> s0s...@gmail.com 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.
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/7/2008 11:28:01 AM
|
|
s0suk3@gmail.com said:
> On Aug 7, 5:53 am, Richard Heathfield <r...@see.sig.invalid> wrote:
>> s0s...@gmail.com 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).
> If not: wouldn't that cause the call to sprintf() to be insecure?
Irrelevant, since it is always sufficient.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/7/2008 12:04:42 PM
|
|
Richard Heathfield <rjh@see.sig.invalid> writes:
> s0suk3@gmail.com said:
>
>> On Aug 7, 5:53 am, Richard Heathfield <r...@see.sig.invalid> wrote:
<snip>
>>> 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.
<snip>
>> 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.
--
Ben.
|
|
0
|
|
|
|
Reply
|
ben.usenet (6515)
|
8/7/2008 12:10:45 PM
|
|
On Aug 7, 7:04 am, Richard Heathfield <rjh@see.sig.invalid> wrote:
> s0suk3@gmail.com said:
>
>
>
> > On Aug 7, 5:53 am, Richard Heathfield <rjh@see.sig.invalid> wrote:
> >> s0suk3@gmail.com 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? 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
|
|
0
|
|
|
|
Reply
|
s0suk3 (372)
|
8/7/2008 12:35:08 PM
|
|
Richard Heathfield wrote:
> CBFalconer said:
>> santosh wrote:
>>> CBFalconer wrote:
>>>
>> ... snip ...
>>>
>>>> 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.
>>
>> In that case I suggest using the %n feature in the format string.
>
> How does that improve matters?
Use the null device to receive the testing run. Most systems have
such a device available.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
|
|
0
|
|
|
|
Reply
|
cbfalconer (19183)
|
8/7/2008 12:38:44 PM
|
|
On Aug 7, 2:20 pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> vipps...@gmail.com writes:
> > On Aug 7, 1:53 pm, Richard Heathfield <r...@see.sig.invalid> wrote:
> >> 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 :-)
|
|
0
|
|
|
|
Reply
|
vippstar (1211)
|
8/7/2008 12:42:50 PM
|
|
Ben Bacarisse said:
> Richard Heathfield <rjh@see.sig.invalid> writes:
>
>> s0suk3@gmail.com said:
<snip>
>>> wouldn't that allocate more space that might be needed?
>>
>> It's possible, yes. For example, if CHAR_BIT is 33 [...] and
>> sizeof(int) is 5, with no padding bits and one sign bit, [...]
>> INT_MAX is a fifty-digit number [...] and my expression
>> [...] yields 166 / 3 = 55, so a massive five bytes are wasted.
>
> I suspect he's worrying about the 54 wasted bytes when converting 0.
Ah, I see - well, he probably isn't using a 33-bit char, 5-byte int
implementation anyway. On a more normal implementation with CHAR_BIT at 8
and sizeof(int) at 4, we get 34 / 3 = 11, which wastes 10 bytes
(temporarily) if the value happens to be 0, but just one if the value is a
ten-decimal-digit number.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/7/2008 12:44:59 PM
|
|
s0suk3@gmail.com said:
> On Aug 7, 7:04 am, Richard Heathfield <rjh@see.sig.invalid> wrote:
>> s0suk3@gmail.com said:
>>
>>
>>
>> > On Aug 7, 5:53 am, Richard Heathfield <rjh@see.sig.invalid> wrote:
>> >> s0suk3@gmail.com 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.
> or malloc()
How is that an advantage over a C90 array?
> if you don't have access to a C99 compiler (unlikely).
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.
> As
> for calculating the required length, I don't think there's a better or
> more elegant way than calling snprintf() twice
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.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/7/2008 12:49:28 PM
|
|
s0suk3@gmail.com wrote:
> On Aug 7, 7:04 am, Richard Heathfield <rjh@see.sig.invalid> wrote:
>> s0suk3@gmail.com said:
>>
>>
>>
>> > On Aug 7, 5:53 am, Richard Heathfield <rjh@see.sig.invalid> wrote:
>> >> s0suk3@gmail.com 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?
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.
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/7/2008 12:57:55 PM
|
|
On Aug 7, 7:49 am, Richard Heathfield <r...@see.sig.invalid> wrote:
> s0s...@gmail.com said:
>
>
>
> > On Aug 7, 7:04 am, Richard Heathfield <r...@see.sig.invalid> wrote:
> >> s0s...@gmail.com said:
>
> >> > On Aug 7, 5:53 am, Richard Heathfield <r...@see.sig.invalid> wrote:
> >> >> s0s...@gmail.com 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.
> > or malloc()
>
> 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.
> > if you don't have access to a C99 compiler (unlikely).
>
> 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.
>
> > As
> > for calculating the required length, I don't think there's a better or
> > more elegant way than calling snprintf() twice
>
> 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
|
|
0
|
|
|
|
Reply
|
s0suk3 (372)
|
8/7/2008 1:16:55 PM
|
|
On Aug 7, 8:16 am, s0suk3@gmail.com wrote:
> On Aug 7, 7:49 am, Richard Heathfield <rjh@see.sig.invalid> wrote:
>
>
>
> > s0suk3@gmail.com said:
>
> > > On Aug 7, 7:04 am, Richard Heathfield <rjh@see.sig.invalid> wrote:
> > >> s0suk3@gmail.com said:
>
> > >> > On Aug 7, 5:53 am, Richard Heathfield <rjh@see.sig.invalid> wrote:
> > >> >> s0suk3@gmail.com 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,
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
|
|
0
|
|
|
|
Reply
|
s0suk3 (372)
|
8/7/2008 1:26:33 PM
|
|
CBFalconer <cbfalconer@yahoo.com> writes:
> Richard Heathfield wrote:
>> CBFalconer said:
>>> santosh wrote:
>>>> CBFalconer wrote:
>>>>
>>> ... snip ...
>>>>
>>>>> 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.
>>>
>>> In that case I suggest using the %n feature in the format string.
>>
>> How does that improve matters?
>
> 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.
|
|
0
|
|
|
|
Reply
|
rgrdev (1814)
|
8/7/2008 1:27:45 PM
|
|
CBFalconer said:
> Richard Heathfield wrote:
>> CBFalconer said:
<snip>
>>>
>>> In that case I suggest using the %n feature in the format string.
>>
>> How does that improve matters?
>
> Use the null device to receive the testing run.
This doesn't answer the question. How does %n improve matters?
> Most systems have such a device available.
I can find nothing in the Standard on "null device". Could you please
provide C&V?
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/7/2008 1:46:12 PM
|
|
s0suk3@gmail.com said:
<snip>
> 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)?
Much of my code is deployed as source. My users can use any conforming C
compiler they like; whether it's C90- or C99-conforming is of no
consequence.
> I've always used GNU GCC's C99 implementation...
They haven't got one.
> I know, I know, they don't claim full C99 conformance.
Well, as long as you know.
> But that's a fact that's never affected me in any way so far.
Pull the ladder up, Jack! :-)
>> > or malloc()
>>
>> 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.
I don't see why it's advantageous to postpone until runtime a calculation
that can be performed trivially at compilation time. There are
circumstances where it is advantageous to use malloc, but I don't see this
as one of them.
<snip>
>> 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.
Assuming you have snprintf, you get that assurance even if you call it once
and then follow up with a call to sprintf.
> By calling snprintf() once,
> you gain the assurance of no overflow, but you still might need to
> make inaccurate size guesses.
No, you get the right size with your first call...
> And by calling sprintf() once,
....you use a buffer of that right size to hand to sprintf.
> you gain neither one of those :(
Ah, I think I understand what you thought I meant. You seem to think that
(given a C99 implementation to work with) I'm offering you three choices:
(1a) snprintf twice
(1b) snprintf once
(1c) sprintf once
I wasn't. I was offering you *two* choices:
(2a) snprintf twice
(2b) snprintf once (to get the size), followed by buffer provision,
followed by sprintf
It is my contention that (2b) is superior to (2a). It is my further
contention that (2b) is not optimal, but we've already had that fight,
right?
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/7/2008 1:58:43 PM
|
|
Richard Heathfield wrote:
> s0suk3@gmail.com said:
>
.... snip ...
>
>> if you don't have access to a C99 compiler (unlikely).
>
> 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.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
|
|
0
|
|
|
|
Reply
|
cbfalconer (19183)
|
8/7/2008 2:02:26 PM
|
|
Richard Heathfield wrote:
> CBFalconer said:
>> Richard Heathfield wrote:
>>> CBFalconer said:
>
> <snip>
>
>>>> In that case I suggest using the %n feature in the format string.
>>>
>>> How does that improve matters?
>>
>> Use the null device to receive the testing run.
>> Most systems have such a device available.
>
> 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.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
|
|
0
|
|
|
|
Reply
|
cbfalconer (19183)
|
8/7/2008 2:14:05 PM
|
|
CBFalconer wrote:
> Richard Heathfield wrote:
>> CBFalconer said:
>>> santosh wrote:
>>>> CBFalconer wrote:
>>>>
>>> ... snip ...
>>>>
>>>>> 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.
>>>
>>> In that case I suggest using the %n feature in the format string.
>>
>> How does that improve matters?
>
> 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.
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/7/2008 2:26:39 PM
|
|
Richard Heathfield wrote:
> s0suk3@gmail.com said:
>> In this particular case it's obvious, isn't it? That you can use
>> runtime evaluation to calculate the required size.
>
> I don't see why it's advantageous to postpone until runtime a
> calculation that can be performed trivially at compilation time.
Would it be as trivial for, say, a long double? I have had cases where
the same long double object produced an output of several lines of
digits for some values and just a few digits for others. Is there a
deterministic formula for doing this at compile-time based only on the
information derivable from float.h?
<snip>
> Ah, I think I understand what you thought I meant. You seem to think
> that (given a C99 implementation to work with) I'm offering you three
> choices:
>
> (1a) snprintf twice
> (1b) snprintf once
> (1c) sprintf once
>
> I wasn't. I was offering you *two* choices:
>
> (2a) snprintf twice
> (2b) snprintf once (to get the size), followed by buffer provision,
> followed by sprintf
>
> It is my contention that (2b) is superior to (2a).
How? 2b isn't any more portable than 2a, and it *might* be
infinitesimally faster. No data loss occurs in either case. So why is
2b superior to 2a?
> It is my further contention that (2b) is not optimal, but we've
> already had that fight, right?
Agreed.
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/7/2008 2:36:26 PM
|
|
> On Thu, 07 Aug 2008 12:04:42 +0000, Richard Heathfield wrote:
> The maximum number of decimal digits an int can represent, plus one for
> the sign and one for the null terminator.
sizeof(int) on my machine is 4 and I tried your expression 4 times:
printf( "max_of_int = %d\n", ( (sizeof(int)* CHAR_BIT) +2 / 3 + 2 ));
printf( "max_of_int = %d\n", ( ((sizeof(int)* CHAR_BIT)) + (2 / 3) + 2) );
printf( "max_of_int = %d\n", ( ( ((sizeof(int)* CHAR_BIT) +2) / 3) + 2) );
printf( "max_of_int = %d\n", ( ((sizeof(int)* CHAR_BIT) +2) / (3 + 2) ));
so, 1st printf() is yours and the only match is second. I will takeit
part by part:
sizeof(int)*CHAR_BIT
why are you multiplying the "size of an int" with "how many bits
in a char" ?
2/3 , it gives what, i mean why it is there ?
+ 2 - okay, one for null character and one for sign
> It's possible, yes. For example, if CHAR_BIT is 33 (i.e. there are 33
> bits in a byte)
and what normal desktop machine have that value, Intel Dual Core, AMD
Athlon 64 3000+ ?
> 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).
> Irrelevant, since it is always sufficient.
hahahaha... It feels like 2 aliens are talking to each other in some
mysterious language...
I did not laugh because of two aliens. Laughing part is "I am paid to
write C Code" when I can't understand your conversation..
and I call myself a Programmer... huh...
--
www.lispmachine.wordpress.com
my email is @ the above blog
check the "About Myself" page
|
|
0
|
|
|
|
Reply
|
sunrise2 (598)
|
8/7/2008 2:37:09 PM
|
|
On Aug 7, 8:58 am, Richard Heathfield <rjh@see.sig.invalid> wrote:
> s0suk3@gmail.com said:
>
> <snip>
>
> > 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)?
>
> Much of my code is deployed as source. My users can use any conforming C
> compiler they like; whether it's C90- or C99-conforming is of no
> consequence.
>
> > I've always used GNU GCC's C99 implementation...
>
> They haven't got one.
>
> > I know, I know, they don't claim full C99 conformance.
>
> Well, as long as you know.
>
> > But that's a fact that's never affected me in any way so far.
>
> Pull the ladder up, Jack! :-)
>
> >> > or malloc()
>
> >> 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.
>
> I don't see why it's advantageous to postpone until runtime a calculation
> that can be performed trivially at compilation time. There are
> circumstances where it is advantageous to use malloc, but I don't see this
> as one of them.
>
> <snip>
>
> >> 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.
>
> Assuming you have snprintf, you get that assurance even if you call it once
> and then follow up with a call to sprintf.
>
> > By calling snprintf() once,
> > you gain the assurance of no overflow, but you still might need to
> > make inaccurate size guesses.
>
> No, you get the right size with your first call...
>
> > And by calling sprintf() once,
>
> ...you use a buffer of that right size to hand to sprintf.
>
> > you gain neither one of those :(
>
> Ah, I think I understand what you thought I meant. You seem to think that
> (given a C99 implementation to work with) I'm offering you three choices:
>
> (1a) snprintf twice
> (1b) snprintf once
> (1c) sprintf once
>
> I wasn't. I was offering you *two* choices:
>
> (2a) snprintf twice
> (2b) snprintf once (to get the size), followed by buffer provision,
> followed by sprintf
>
I see. But if you call snprintf() first to tell you the size, it's
completely irrelevant whether in the second call you use sprintf() or
snprintf(); it's merely a matter of implicitness or explicitness.
(Small exception: as CBFalconer mentioned, if, for some reason, the
value to be converted might change between the two calls, being
explicit about the size and using snprintf() for the second call would
be safer.)
<snip>
Sebastian
|
|
0
|
|
|
|
Reply
|
s0suk3 (372)
|
8/7/2008 2:43:55 PM
|
|
santosh said:
> Richard Heathfield wrote:
>
>> s0suk3@gmail.com said:
>
>
>>> In this particular case it's obvious, isn't it? That you can use
>>> runtime evaluation to calculate the required size.
>>
>> I don't see why it's advantageous to postpone until runtime a
>> calculation that can be performed trivially at compilation time.
>
> Would it be as trivial for, say, a long double? I have had cases where
> the same long double object produced an output of several lines of
> digits for some values and just a few digits for others. Is there a
> deterministic formula for doing this at compile-time based only on the
> information derivable from float.h?
Assuming you mean a full decimal representation, well, it's pretty simple -
you need at least LDBL_MAX_10_EXP bytes. In practice, however, one doesn't
do this, because in practice one has a good idea of the range of values
that is pertinent to the problem domain, and one can work out exactly how
much storage is required for valid values; invalid values are rejected. I
think I already mentioned this.
<snip>
>> (2a) snprintf twice
>> (2b) snprintf once (to get the size), followed by buffer provision,
>> followed by sprintf
>>
>> It is my contention that (2b) is superior to (2a).
>
> How? 2b isn't any more portable than 2a,
Agreed.
> and it *might* be infinitesimally faster. No data loss occurs
> in either case. So why is 2b superior to 2a?
It's infinitesimally faster - or at least it might be! But more to the
point, it's less to type, so less to get wrong.
<snip>
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/7/2008 2:52:43 PM
|
|
arnuld said:
>> On Thu, 07 Aug 2008 12:04:42 +0000, Richard Heathfield wrote:
>
>
>> The maximum number of decimal digits an int can represent, plus one for
>> the sign and one for the null terminator.
>
> sizeof(int) on my machine is 4 and I tried your expression 4 times:
>
>
> printf( "max_of_int = %d\n", ( (sizeof(int)* CHAR_BIT) +2 / 3 + 2 ));
That's not mine.
> printf( "max_of_int = %d\n", ( ((sizeof(int)* CHAR_BIT)) + (2 / 3) + 2)
Neither is that.
> ); printf( "max_of_int = %d\n", ( ( ((sizeof(int)* CHAR_BIT) +2) / 3) +
> 2) );
That's equivalent to mine.
> printf( "max_of_int = %d\n", ( ((sizeof(int)* CHAR_BIT) +2) / (3 + 2)
> ));
That's not mine.
> so, 1st printf() is yours and the only match is second. I will takeit
> part by part:
>
> sizeof(int)*CHAR_BIT
>
> why are you multiplying the "size of an int" with "how many bits
> in a char" ?
To get the number of bits in an int.
> 2/3 , it gives what, i mean why it is there ?
No idea. That's your invention, not mine.
>> It's possible, yes. For example, if CHAR_BIT is 33 (i.e. there are 33
>> bits in a byte)
>
> and what normal desktop machine have that value, Intel Dual Core, AMD
> Athlon 64 3000+ ?
Think "hypothetical example chosen at random".
> Laughing part is "I am paid to
> write C Code" when I can't understand your conversation..
That's scary, since nobody here is saying anything that is difficult to
understand.
> and I call myself a Programmer... huh...
I couldn't possibly comment.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/7/2008 2:57:18 PM
|
|
Richard Heathfield wrote:
> santosh said:
>> Richard Heathfield wrote:
>>
.... snip ...
>>
>>> (2a) snprintf twice
>>> (2b) snprintf once (to get the size), followed by buffer provision,
>>> followed by sprintf
>>>
>>> It is my contention that (2b) is superior to (2a).
>>
>> How? 2b isn't any more portable than 2a,
>
> Agreed.
>
>> and it *might* be infinitesimally faster. No data loss occurs
>> in either case. So why is 2b superior to 2a?
>
> It's infinitesimally faster - or at least it might be! But more to
> the point, it's less to type, so less to get wrong.
Possibly. However, it probably significantly increases the amount
of code loaded from the library. This may significantly increase
the runtime module size, assuming static library. Two functions
are normally bigger than one.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
|
|
0
|
|
|
|
Reply
|
cbfalconer (19183)
|
8/7/2008 3:00:52 PM
|
|
CBFalconer said:
> Richard Heathfield wrote:
>> CBFalconer said:
>>> Richard Heathfield wrote:
>>>> CBFalconer said:
>>
>> <snip>
>>
>>>>> In that case I suggest using the %n feature in the format string.
>>>>
>>>> How does that improve matters?
>>>
>>> Use the null device to receive the testing run.
>>> Most systems have such a device available.
>>
>> 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.
Which you can get from the return value anyway. How does %n improve
matters? (Third time of asking.)
> From this you can resolve the size of buffer
> needed, and malloc it.
That may not be necessary, as I have said several times in this thread.
> Admittedly finding the system null device
> is a nuisance, and non-portable.
Right, so it's inadmissible here.
> I published, and you snipped, the
> standard sections on the %n feature.
What I asked was *why* you thought %n was an advantage, compared to a
simple capture of the return value. I did not ask you to explain what %n
does. You see, we all *know* what %n does, and in any case your article is
still available for all to see. I snipped your Standard quotes because
they didn't have the slightest bearing on the current discussion. That's
good snip, not bad snip.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/7/2008 3:02:20 PM
|
|
s0suk3@gmail.com said:
<snip>
> I see. But if you call snprintf() first to tell you the size, it's
> completely irrelevant whether in the second call you use sprintf() or
> snprintf();
Yes, the difference is miniscule.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/7/2008 3:03:32 PM
|
|
In article <489B0072.1791BA84@yahoo.com>,
CBFalconer <cbfalconer@maineline.net> wrote:
>Richard Heathfield wrote:
>> s0suk3@gmail.com said:
>>
>... snip ...
>>
>>> if you don't have access to a C99 compiler (unlikely).
>>
>> 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.
It looks very much like someone has hacked CBF's account. This does not
sound at all like the CBF we all knew.
Anyway, the dogma of the group (certain that of RH) is "all or its crap".
If you can find one little thing to nit-pick about, then the
implementation is crap.
Besides that, is the fact that the dogma of the group has also always been
that the compilers listed above (namely, Microsoft [i.e., Windows], gcc
[i.e., Linux] and Borland [i.e., DOS/Windows]) represent a miniscule and
essentially irrelevant part of the C world. That the "big money" is in
embedded systems (not hosted) and that what really matters is all the
(unnamed) compilers for embedded systems (that we never hear about on
this group - funny, that)
|
|
0
|
|
|
|
Reply
|
gazelle2 (1306)
|
8/7/2008 3:36:46 PM
|
|
Richard Heathfield wrote:
> CBFalconer said:
>
>> Richard Heathfield wrote:
>>> CBFalconer said:
>>>> Richard Heathfield wrote:
>>>>> CBFalconer said:
>>>
>>> <snip>
>>>
>>>>>> In that case I suggest using the %n feature in the format string.
>>>>>
>>>>> How does that improve matters?
>>>>
>>>> Use the null device to receive the testing run.
>>>> Most systems have such a device available.
>>>
>>> This doesn't answer the question. How does %n improve matters?
<snip>
In this call:
int ret = 0;
int n = 0;
ret = fprintf(temp_file, "%p%n", (void*)ptr, n);
If an output error occurred after the 'p' specifier had been processed,
n will still contain the number of characters written out, while ret
will contain a negative value.
But I think this is not likely at all.
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/7/2008 3:54:10 PM
|
|
CBFalconer <cbfalconer@yahoo.com> writes:
> Richard Heathfield wrote:
>> s0suk3@gmail.com said:
>>
> ... snip ...
>>
>>> if you don't have access to a C99 compiler (unlikely).
>>
>> 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.
No, if you need to produce code that will run on multiple systems, you
may need multiple compilers. And if you're distributing source code,
you need to ensure that the code will be compatible with your users'
compilers, which you might not have access to.
Given the current state of the market, the best way to ensure that is
to restrict yourself to the intersection of C90 and C99. If you use,
say, gcc for your own system, you can take advantage of the features
that gcc offers -- but what if your users want to compile your code on
a system that doesn't have gcc? Or what if they want to use a
different compiler because it generates faster code for their system
than gcc does?
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
kst-u (21467)
|
8/7/2008 4:44:07 PM
|
|
Keith Thompson wrote:
> CBFalconer <cbfalconer@yahoo.com> writes:
[ ... ]
>> 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.
>
> No, if you need to produce code that will run on multiple systems, you
> may need multiple compilers. And if you're distributing source code,
> you need to ensure that the code will be compatible with your users'
> compilers, which you might not have access to.
>
> Given the current state of the market, the best way to ensure that is
> to restrict yourself to the intersection of C90 and C99.
Which is more or less C90.
<snip>
|
|
0
|
|
|
|
Reply
|
santosh.k83 (3969)
|
8/7/2008 4:55:44 PM
|
|
On 7 Aug 2008 at 3:46, Keith Thompson wrote:
> CBFalconer <cbfalconer@yahoo.com> writes:
>> 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.
>
> First off, a conforming implementation could, for example, say that
> the "%p" conversion yields a random number of underscores followed by
> the pointer representation in hexadecimal. *scanf would just ignore
> the underscores. This would be a silly implementation, but I believe
> it would be conforming.
It is absolutely astonishing that two grown-up people can conduct a
conversation about nonsense like this, apparently in all seriousness.
|
|
0
|
|
|
|
Reply
|
nospam59 (9755)
|
8/7/2008 7:31:45 PM
|
|
Keith Thompson said:
> CBFalconer <cbfalconer@yahoo.com> writes:
>> Richard Heathfield wrote:
<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.
>
> No, if you need to produce code that will run on multiple systems, you
> may need multiple compilers. And if you're distributing source code,
> you need to ensure that the code will be compatible with your users'
> compilers, which you might not have access to.
Those two sentences summarise my own predicament rather nicely.
> Given the current state of the market, the best way to ensure that is
> to restrict yourself to the intersection of C90 and C99.
Which is precisely what I do (most of the time).
> If you use,
> say, gcc for your own system, you can take advantage of the features
> that gcc offers -- but what if your users want to compile your code on
> a system that doesn't have gcc? Or what if they want to use a
> different compiler because it generates faster code for their system
> than gcc does?
I am delighted to be able to report that, on occasion, I /can/ take
advantage of compiler-specific features. Alas, it doesn't happen as often
as I'd like, but it /does/ happen... from time to time.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/7/2008 8:10:10 PM
|
|
santosh <santosh.k83@gmail.com> writes:
> Keith Thompson wrote:
>> CBFalconer <cbfalconer@yahoo.com> writes:
>
> [ ... ]
>
>>> 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.
>>
>> No, if you need to produce code that will run on multiple systems, you
>> may need multiple compilers. And if you're distributing source code,
>> you need to ensure that the code will be compatible with your users'
>> compilers, which you might not have access to.
>>
>> Given the current state of the market, the best way to ensure that is
>> to restrict yourself to the intersection of C90 and C99.
>
> Which is more or less C90.
Right. To quantify the "more or less", you have to avoid implicit int
and using any of the new C99 keywords (inline, restrict, are there
others?) as identifiers, and probably a few other things I haven't
thought of.
More generally, you have to avoid anything that conflicts with C99.
For example, writing your own "bool.h" or "complex.h" header would be
a bad idea.
Note that C99 keywords like _Bool aren't an issue, since you can't
portably use them in C90 anyway.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
kst-u (21467)
|
8/7/2008 9:18:41 PM
|
|
Richard Heathfield wrote:
> CBFalconer said:
>> Richard Heathfield wrote:
>>
.... snip ...
>>
>>> 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.
>
> Which you can get from the return value anyway. How does %n
> improve matters? (Third time of asking.)
Didn't realize, in the heat of the news replying, that I could just
use the *printf returned value. I have even been known to use it.
Then the only useful idea in that particular set is using the
(occasionally available) null device. And the only real purpose of
%n is to take length measurements in the middle of the *printf
call.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
|
|
0
|
|
|
|
Reply
|
cbfalconer (19183)
|
8/7/2008 9:20:56 PM
|
|
> On Thu, 07 Aug 2008 14:57:18 +0000, Richard Heathfield wrote:
>> arnuld said:
>> (sizeof(int)* CHAR_BIT) +2) / 3 + 2;
> That's equivalent to mine.
okay
> To get the number of bits in an int.
so, my machine has 32 bytes in an int
>> 2/3 , it gives what, i mean why it is there ?
> No idea. That's your invention, not mine.
your example: sizeof(int) * CHAR_BIT + 2, its okay till here. 32 bytes +
2 bytes more ( 1 more sign and 1 for null character)
now you divide that expression by 3 and then add 2 to it. Why ?
> I couldn't possibly comment.
thanks
--
www.lispmachine.wordpress.com
my email is @ the above blog
check the "About Myself" page
|
|
0
|
|
|
|
Reply
|
sunrise2 (598)
|
8/8/2008 4:29:19 AM
|
|
arnuld said:
>> On Thu, 07 Aug 2008 14:57:18 +0000, Richard Heathfield wrote:
<snip>
>> To get the number of bits in an int.
>
> so, my machine has 32 bytes in an int
That's a lot of bytes.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/8/2008 8:14:36 AM
|
|
Hello,
arnuld schrieb:
>> On Thu, 07 Aug 2008 14:57:18 +0000, Richard Heathfield wrote:
> your example: sizeof(int) * CHAR_BIT + 2, its okay till here. 32 bytes +
> 2 bytes more ( 1 more sign and 1 for null character)
>
> now you divide that expression by 3 and then add 2 to it. Why ?
Ok, let's take the original expression again:
(sizeof(int) * CHAR_BIT + 2) / 3 + 2
The + 2 at the end is clear and already explained by RH;
sizeof(int)*CHAR_BIT is the number of bits the int occupies. I'll call
it BITS_OF_AN_INT.
So, the only "problamtic" part is: (BITS_OF_AN_INT + 2 ) / 3.
Here, RH is "cheating": In fact, he does not calculate the number of
digits in the decimal system. He calculates the number of digits in
octal!
3 bits build up 1 octal digit, much like 4 bits build up 1 hexadecimal
digit. So, he divides BITS_OF_AN_INT by 3. The "+ 2" makes sure that his
calculation has a ceiling, that is, rounds up.
I hope this clarifies the calculation.
However, IMHO, it is not really obvious. Richard (RH), I hope you
clearly document this whenever you use it.
Regards,
Spiro.
"Anybody who would spend considerable effort emulating a C64 is not
particularly sane to begin with; it is unreasonable to expect them to produce
sane software."
("asuffield" in http://forums.thedailywtf.com/forums/p/7199/134136.aspx)
--
Spiro R. Trikaliotis http://opencbm.sf.net/
http://www.trikaliotis.net/ http://www.viceteam.org/
|
|
0
|
|
|
|
Reply
|
news-200803 (15)
|
8/8/2008 9:18:35 AM
|
|
> On Fri, 08 Aug 2008 08:14:36 +0000, Richard Heathfield wrote:
> That's a lot of bytes.
eeee....... Richard :P
I *really* want to know why you divided the whole thing by 3 and added 2
to the result.
I know the final result is number of decimal digits an int can represent,
which is the maximum value of int on a machine. I am asking is that some
kind of formula like n(n+1)/2 ?
--
www.lispmachine.wordpress.com
my email is @ the above blog
check the "About Myself" page
|
|
0
|
|
|
|
Reply
|
sunrise2 (598)
|
8/8/2008 9:18:47 AM
|
|
Hello,
I wrote:
> Here, RH is "cheating": In fact, he does not calculate the number of
> digits in the decimal system. He calculates the number of digits in
> octal!
Of course, one has to remember that the octal representation needs at
least as many digits as the decimal representation. Without this fact,
this calculation would be pointless.
Regards,
Spiro.
"Anybody who would spend considerable effort emulating a C64 is not
particularly sane to begin with; it is unreasonable to expect them to produce
sane software."
("asuffield" in http://forums.thedailywtf.com/forums/p/7199/134136.aspx)
--
Spiro R. Trikaliotis http://opencbm.sf.net/
http://www.trikaliotis.net/ http://www.viceteam.org/
|
|
0
|
|
|
|
Reply
|
news-200803 (15)
|
8/8/2008 9:22:14 AM
|
|
Spiro Trikaliotis said:
> Hello,
>
> arnuld schrieb:
>>> On Thu, 07 Aug 2008 14:57:18 +0000, Richard Heathfield wrote:
>
>> your example: sizeof(int) * CHAR_BIT + 2, its okay till here. 32 bytes
>> + 2 bytes more ( 1 more sign and 1 for null character)
>>
>> now you divide that expression by 3 and then add 2 to it. Why ?
>
> Ok, let's take the original expression again:
>
> (sizeof(int) * CHAR_BIT + 2) / 3 + 2
>
> The + 2 at the end is clear and already explained by RH;
Right. Actually, I explained the entire calculation, for a variety of
number bases, on 22 July of this year (i.e. about two weeks ago). Here is
the message ID: <5qGdnak6FpYIDBjVnZ2dnUVZ8uSdnZ2d@bt.com>
Perhaps I should do a Web page (sigh).
<snip>
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
|
|
0
|
|
|
|
Reply
|
rjh (10789)
|
8/8/2008 10:22:49 AM
|
|
Hello Richard,
Richard Heathfield <rjh@see.sig.invalid> schrieb:
> Right. Actually, I explained the entire calculation, for a variety of
> number bases, on 22 July of this year (i.e. about two weeks ago).
Oh, I missed that one. On 22 July? I was on vacation on that day. ;)
Regards,
Spiro.
"Anybody who would spend considerable effort emulating a C64 is not
particularly sane to begin with; it is unreasonable to expect them to produce
sane software."
("asuffield" in http://forums.thedailywtf.com/forums/p/7199/134136.aspx)
--
Spiro R. Trikaliotis http://opencbm.sf.net/
http://www.trikaliotis.net/ http://www.viceteam.org/
|
|
0
|
|
|
|
Reply
|
news-200803 (15)
|
8/8/2008 11:01:25 AM
|
|
On Wed, 06 Aug 2008 16:17:16 +0000, Kenny McCormack wrote:
> In article <g7cfdc$quv$2@registered.motzarella.org>, santosh
> <santosh.k83@gmail.com> wrote:
>>CBFalconer wrote:
>>
>>> santosh wrote:
>>>> Richard Heathfield wrote:
>>>>
>>> ... snip ...
>>>>
>>>>> open a shell, find the program, run the program from the shell.
>>>>
>>>> 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.
>>
>>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?
Thank you Judas for the victim;
Stay a while; you'll watch it bleed.
>
> (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.)
I think santosh prefers the C programming language to a syntax equivalent
of the american playground classic: smear the queer.
--
Howard
|
|
0
|
|
|
|
Reply
|
invalid1857 (21)
|
8/9/2008 3:50:42 AM
|
|
arnuld <sunrise@invalid.address> writes:
>>1) find out how much storage you need for the string;
>>2) allocate that much;
>>3) call sprintf to build the string.
>you mean you missed the 4th step ;)
>1) find out how much storage you need for the string
>2) malloc() that much
>3) call sprintf to build the string
>4) don't forget to free() the memory
Still, both of you did not check the result of malloc.
|
|
0
|
|
|
|
Reply
|
ram (2826)
|
10/14/2009 10:44:49 AM
|
|
ram@zedat.fu-berlin.de (Stefan Ram) writes:
> arnuld <sunrise@invalid.address> writes:
>>>1) find out how much storage you need for the string;
>>>2) allocate that much;
>>>3) call sprintf to build the string.
>>you mean you missed the 4th step ;)
>>1) find out how much storage you need for the string
>>2) malloc() that much
>>3) call sprintf to build the string
>>4) don't forget to free() the memory
>
> Still, both of you did not check the result of malloc.
>
Why bother? It malloc fails for a few bytes your system is almost
certainly irrecoverable ..........
Besides that, he didn't NEED to specifically state the check because (2)
includes (or possibly includes), the check since its target was to
"malloc() that much". if malloc failed, then the target was not met.
J
--
"Avoid hyperbole at all costs, its the most destructive argument on
the planet" - Mark McIntyre in comp.lang.c
|
|
0
|
|
|
|
Reply
|
rgrdev_ (1087)
|
10/14/2009 12:47:01 PM
|
|
|
178 Replies
65 Views
(page loaded in 1.05 seconds)
|