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
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
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
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
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.
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
> 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
> 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
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
> 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.
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
<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.
--
Ian Collins.
> 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.
#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.
No, alloca() is not part of any C standard, so using it does not really
prove that there is a problem.
--
Flash Gordon
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.
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
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
> Ron Ford <r...@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
> 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
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) ks...@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"
You can try Eclipse and have the plug-in CDT (C/C++ Development Tool)
equipped together. The combination requires other compiler and
debugger.
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
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
>
> 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...
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
<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
> 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
> 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.
You guys are nuts. I'm going with Pele in his prime.
;-)
** Posted from http://www.teranews.com **
> "Richard Heathfield" <r...@see.sig.invalid> wrote in message
> news:tfadnXfEvJeBFhvV...@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
>> "Richard Heathfield" <r...@see.sig.invalid> wrote in message
>> news:tfadnXfEvJeBFhvV...@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.a...@40tude.net>
Ron Ford <r...@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.
<snip>
> In article <riqlu8dork8r.a...@40tude.net>
> Ron Ford <r...@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>
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.
> 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
>> 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].
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.
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.
> 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 ?
> 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 ;)
>> 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.
<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>
> 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.
> 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.
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
<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.
> 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!
> 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.
>> 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.
>> 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>
<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.
<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 <r...@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>
> 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.
Oops sorry about all the syntax errors in that code.
> Richard Heathfield <r...@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.
> Ben Bacarisse said:
>
>> Richard Heathfield <r...@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.
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
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]
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.
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
>> 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.
>> 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( ..... )
>> 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?
>> 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.
<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.
> 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.
> 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.
>> 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.
> 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.
> 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 ?
>> 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.
>> 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.
>> 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.
<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.
<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. :-)
>> 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.
> 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
> 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. :-)
> Then stick with snprintf.
:(
> In fact, stick with Visual Basic.
Richard....... no... I hate VB
[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)
>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 <santo...@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
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.
> 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>
> 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.
> 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. :-)
<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();
> 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.
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.
<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.
What's wrong with:
open a shell, find the program, run the program from the shell.
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
> 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.
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>
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.
Now that is unnecessary nasty treatment of a newbie.