Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #107805 > unrolled thread
| Started by | MehdiAmini <atorrses@gmail.com> |
|---|---|
| First post | 2017-04-07 12:20 +0430 |
| Last post | 2017-04-08 20:34 +0430 |
| Articles | 20 on this page of 55 — 9 participants |
Back to article view | Back to comp.lang.c
How to fix: [-Wformat-nonliteral] MehdiAmini <atorrses@gmail.com> - 2017-04-07 12:20 +0430
Re: How to fix: [-Wformat-nonliteral] Barry Schwarz <schwarzb@dqel.com> - 2017-04-07 01:28 -0700
Re: How to fix: [-Wformat-nonliteral] David Brown <david.brown@hesbynett.no> - 2017-04-07 11:58 +0200
Re: How to fix: [-Wformat-nonliteral] Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-04-07 11:43 +0100
Re: How to fix: [-Wformat-nonliteral] David Brown <david.brown@hesbynett.no> - 2017-04-07 13:35 +0200
Re: How to fix: [-Wformat-nonliteral] Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-04-07 13:50 +0100
Re: How to fix: [-Wformat-nonliteral] David Brown <david.brown@hesbynett.no> - 2017-04-07 15:54 +0200
Re: How to fix: [-Wformat-nonliteral] Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-04-07 19:35 +0100
Re: How to fix: [-Wformat-nonliteral] David Brown <david.brown@hesbynett.no> - 2017-04-08 13:41 +0200
Re: How to fix: [-Wformat-nonliteral] supercat@casperkitty.com - 2017-04-10 13:52 -0700
Re: How to fix: [-Wformat-nonliteral] David Brown <david.brown@hesbynett.no> - 2017-04-11 00:18 +0200
Re: How to fix: [-Wformat-nonliteral] supercat@casperkitty.com - 2017-04-10 15:43 -0700
Re: How to fix: [-Wformat-nonliteral] Keith Thompson <kst-u@mib.org> - 2017-04-10 16:10 -0700
Re: How to fix: [-Wformat-nonliteral] supercat@casperkitty.com - 2017-04-10 16:26 -0700
Re: How to fix: [-Wformat-nonliteral] David Brown <david.brown@hesbynett.no> - 2017-04-11 11:33 +0200
Re: How to fix: [-Wformat-nonliteral] supercat@casperkitty.com - 2017-04-11 08:37 -0700
Re: How to fix: [-Wformat-nonliteral] David Brown <david.brown@hesbynett.no> - 2017-04-13 00:20 +0200
Re: How to fix: [-Wformat-nonliteral] supercat@casperkitty.com - 2017-04-12 15:55 -0700
Re: How to fix: [-Wformat-nonliteral] Keith Thompson <kst-u@mib.org> - 2017-04-12 18:17 -0700
Re: How to fix: [-Wformat-nonliteral] David Brown <david.brown@hesbynett.no> - 2017-04-14 12:27 +0200
Re: How to fix: [-Wformat-nonliteral] supercat@casperkitty.com - 2017-04-14 11:57 -0700
Re: How to fix: [-Wformat-nonliteral] David Brown <david.brown@hesbynett.no> - 2017-04-17 18:08 +0200
Re: How to fix: [-Wformat-nonliteral] supercat@casperkitty.com - 2017-04-17 09:38 -0700
Re: How to fix: [-Wformat-nonliteral] Keith Thompson <kst-u@mib.org> - 2017-04-12 18:13 -0700
Re: How to fix: [-Wformat-nonliteral] supercat@casperkitty.com - 2017-04-13 07:37 -0700
Re: How to fix: [-Wformat-nonliteral] Keith Thompson <kst-u@mib.org> - 2017-04-13 08:43 -0700
Re: How to fix: [-Wformat-nonliteral] supercat@casperkitty.com - 2017-04-13 11:24 -0700
Re: How to fix: [-Wformat-nonliteral] Keith Thompson <kst-u@mib.org> - 2017-04-13 11:49 -0700
Re: How to fix: [-Wformat-nonliteral] Robert Wessel <robertwessel2@yahoo.com> - 2017-04-13 14:43 -0500
Re: How to fix: [-Wformat-nonliteral] supercat@casperkitty.com - 2017-04-13 13:26 -0700
Re: How to fix: [-Wformat-nonliteral] Keith Thompson <kst-u@mib.org> - 2017-04-13 13:32 -0700
Re: How to fix: [-Wformat-nonliteral] supercat@casperkitty.com - 2017-04-13 14:27 -0700
Re: How to fix: [-Wformat-nonliteral] Robert Wessel <robertwessel2@yahoo.com> - 2017-04-13 17:39 -0500
Re: How to fix: [-Wformat-nonliteral] supercat@casperkitty.com - 2017-04-13 16:16 -0700
Re: How to fix: [-Wformat-nonliteral] Tim Rentsch <txr@alumni.caltech.edu> - 2017-04-16 17:53 -0700
Re: How to fix: [-Wformat-nonliteral] supercat@casperkitty.com - 2017-04-13 13:19 -0700
Re: How to fix: [-Wformat-nonliteral] Tim Rentsch <txr@alumni.caltech.edu> - 2017-04-16 17:49 -0700
Re: How to fix: [-Wformat-nonliteral] David Brown <david.brown@hesbynett.no> - 2017-04-17 18:14 +0200
Re: How to fix: [-Wformat-nonliteral] Keith Thompson <kst-u@mib.org> - 2017-04-17 11:54 -0700
Re: How to fix: [-Wformat-nonliteral] David Brown <david.brown@hesbynett.no> - 2017-04-17 22:41 +0200
Re: How to fix: [-Wformat-nonliteral] Keith Thompson <kst-u@mib.org> - 2017-04-17 15:02 -0700
Re: How to fix: [-Wformat-nonliteral] David Brown <david.brown@hesbynett.no> - 2017-04-14 12:40 +0200
Re: How to fix: [-Wformat-nonliteral] supercat@casperkitty.com - 2017-04-14 12:10 -0700
Re: How to fix: [-Wformat-nonliteral] Keith Thompson <kst-u@mib.org> - 2017-04-14 13:22 -0700
Re: How to fix: [-Wformat-nonliteral] supercat@casperkitty.com - 2017-04-14 17:14 -0700
Re: How to fix: [-Wformat-nonliteral] David Brown <david.brown@hesbynett.no> - 2017-04-13 00:20 +0200
Re: How to fix: [-Wformat-nonliteral] MehdiAmini <atorrses@gmail.com> - 2017-04-07 20:29 +0430
Re: How to fix: [-Wformat-nonliteral] David Brown <david.brown@hesbynett.no> - 2017-04-07 18:42 +0200
Re: How to fix: [-Wformat-nonliteral] MehdiAmini <atorrses@gmail.com> - 2017-04-08 08:04 +0430
Re: How to fix: [-Wformat-nonliteral] Richard Heathfield <rjh@cpax.org.uk> - 2017-04-08 07:51 +0100
Re: How to fix: [-Wformat-nonliteral] MehdiAmini <atorrses@gmail.com> - 2017-04-08 12:11 +0430
Re: How to fix: [-Wformat-nonliteral] Richard Heathfield <rjh@cpax.org.uk> - 2017-04-08 11:38 +0100
Re: How to fix: [-Wformat-nonliteral] Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-04-08 18:52 +0100
Re: How to fix: [-Wformat-nonliteral] David Brown <david.brown@hesbynett.no> - 2017-04-08 13:48 +0200
Re: How to fix: [-Wformat-nonliteral] MehdiAmini <atorrses@gmail.com> - 2017-04-08 20:34 +0430
Page 2 of 3 — ← Prev page 1 [2] 3 Next page →
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-04-14 11:57 -0700 |
| Message-ID | <ed31f78a-0088-4cd2-a564-e107e2575f71@googlegroups.com> |
| In reply to | #108120 |
On Friday, April 14, 2017 at 5:27:52 AM UTC-5, David Brown wrote:
> The standards make it clear that program lifetime objects without
> explicit initialisation are zero'ed before the start of the program. A
> freestanding C implementation can use whatever it likes as a start
> function - it can be "void main(void)", or "int reset(int)", or whatever
> it wants. That is for the implementation to decide. And if the
> programmer uses a form that is not specified by the implementation, then
> /that/ is undefined behaviour.
The notion of "the start of a program" can be somewhat murky in some free-
standing scenarios. Many C-language tools generate code for independent
functions; once a collection of functions is loaded and RAM is set up for
them, any of them could be executed directly without having previously run
any other code produced by the C-language tools. Responsibility for any
zero-initialization would lie with the external loading process.
TI does bundle some assembly-language files which can be adjusted to
accommodate a variety of loading scenarios (code runs from flash; code gets
loaded into RAM from an external storage device and then run, etc.), and
it would probably have been a good idea to have them default to zero-
initializing storage. I'm not sure whether such files should be viewed as
really being part of the "C implementation", however, since one could do C
programming without them if e.g. one had a boot loader that could process
ELF files directly and set up RAM according to that spec (including zero-
initialization).
> Clearly it is possible to write code that can be run by the second
> implementation. And clearly it is possible to write code that /cannot/
> be run by the first implementation (just use enough constant data to
> overflow the ram in the microcontroller, avoiding the
> implementation-specific features needed to keep that constant data in
> flash). But with the second implementation, standard programs that
> should be able to run (i.e., they are within the limitations of ram,
> rom, etc.), will compile cleanly but have different and incorrect
> behaviour compared to other conforming C implementations. And that is
> the vital difference.
I've not had problems with the const-pointer treatment breaking code; I'm
not sure how much otherwise-usable code would be broken by it. On many
parts, the difference in RAM and ROM sizes is sufficiently large (30:1 or
more) that a lot of programs would be nowhere close to being able to store
all their tables in RAM, but would still be nowhere near filling their code
space.
> The problem is non-const data accessed through const qualified pointers.
> And such code /is/ common:
>
> extern int average(int noOfSamples, const int * pSamples);
> int x[10];
> int av = average(10, x);
On the PIC compilers, that will work without difficulty. The act of reading
a const pointer causes the compiler to check a bit in the pointer and either
access RAM or ROM. The situations the PIC has trouble with are using non-
const pointers to read const data, or round-tripping const pointers through
non-const pointers, but of which are much rarer than using const pointers to
read both const and non-const data.
I don't know what the Atmel compiler does, but if it can't use const pointers
to read non-const data I would agree that is an unjustifiable abuse of the
"const" keyword which doesn't accommodate any useful scenarios that would not
be served just as well using a different keyword. The reason I regard the
PIC's behavior as somewhat reasonable [albeit obviously non-conforming] is
that it allows many programs to run efficiently without modification in a
way which would not be possible had another keyword been chosen. If the
Atmel compiler's implementation doesn't offer that advantage, I would see
no justification for re-purposing the keyword.
> A C compiler should not be made to work only with a particular
> specialised variety of programs! A compiler sold as a "C Compiler"
> should be made to correctly compile as many valid C programs as possible
> given the limitations of the target.
Since only a particular specialized variety of programs could possibly
do anything useful with 36 bytes of RAM and 1Kword of code space, it would
be impossible to write a compiler for such a platform that *wasn't* limited
to a particular specialized variety of programs.
More generally, most embedded compilers are intended largely for use on
systems which don't have any defined concept of console or file I/O, and
could thus only process usefully the particular specialized variety of
programs that are designed to operate with whatever hardware is built into
the target system.
The advantage of using C on many such systems isn't that one can simply grab
arbitrary bits of code from here and there and run it, but rather that a
programmer who wants to turn on a light need only worry about:
1. Which I/O port is the light hooked up to
2. Which bits of which addresses need to be written to activate that
port
Rather than also having to worry about the sequence of instructions that
might be needed to perform such an access, any restrictions that might exist
regarding the placement of such code and any data it requires, and also the
question of what one must do to ensure that code gets put into whatever kind
of code section is required on the target. The placement of the light and
the sequence of accesses needed to activate it will vary depending upon the
hardware platform, but there's no reason the syntax for performing such
accesses should need to.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-04-17 18:08 +0200 |
| Message-ID | <od2p42$vhl$1@dont-email.me> |
| In reply to | #108147 |
On 14/04/17 20:57, supercat@casperkitty.com wrote: > On Friday, April 14, 2017 at 5:27:52 AM UTC-5, David Brown wrote: <snip> > I've not had problems with the const-pointer treatment breaking code; I'm > not sure how much otherwise-usable code would be broken by it. On many > parts, the difference in RAM and ROM sizes is sufficiently large (30:1 or > more) that a lot of programs would be nowhere close to being able to store > all their tables in RAM, but would still be nowhere near filling their code > space. If you haven't used a compiler where turning a non-const pointer into a const pointer breaks things, then of course you won't have had problems with it. Most compilers are perfectly happy with such conversions. > >> The problem is non-const data accessed through const qualified pointers. >> And such code /is/ common: >> >> extern int average(int noOfSamples, const int * pSamples); >> int x[10]; >> int av = average(10, x); > > On the PIC compilers, that will work without difficulty. The act of reading > a const pointer causes the compiler to check a bit in the pointer and either > access RAM or ROM. The situations the PIC has trouble with are using non- > const pointers to read const data, or round-tripping const pointers through > non-const pointers, but of which are much rarer than using const pointers to > read both const and non-const data. Those will be rarer situations, but may still mean legal code will fail. > > I don't know what the Atmel compiler does, Please stop referring to this compiler as "the Atmel compiler". It was a compiler written by an independent development tool company for one of Atmel's microcontroller families - it was /not/ a compiler from Atmel. > but if it can't use const pointers > to read non-const data I would agree that is an unjustifiable abuse of the > "const" keyword which doesn't accommodate any useful scenarios that would not > be served just as well using a different keyword. Great, you agree with the point I made a good many posts at the start of this sub-thread. > The reason I regard the > PIC's behavior as somewhat reasonable [albeit obviously non-conforming] is > that it allows many programs to run efficiently without modification in a > way which would not be possible had another keyword been chosen. I agree that such behaviour is "somewhat reasonable". I'd much prefer a command line switch, however. > If the > Atmel compiler's implementation doesn't offer that advantage, I would see > no justification for re-purposing the keyword. The compiler I was talking about allowed /some/ programs to run more efficiently without modification (specifically, those that had a lot of constant data but never accessed non-const data through a const pointer). But it would silently break other programs. > >> A C compiler should not be made to work only with a particular >> specialised variety of programs! A compiler sold as a "C Compiler" >> should be made to correctly compile as many valid C programs as possible >> given the limitations of the target. > > Since only a particular specialized variety of programs could possibly > do anything useful with 36 bytes of RAM and 1Kword of code space, it would > be impossible to write a compiler for such a platform that *wasn't* limited > to a particular specialized variety of programs. That is why I added the qualification "as many as possible /given the limitations of the target/". > > More generally, most embedded compilers are intended largely for use on > systems which don't have any defined concept of console or file I/O, and > could thus only process usefully the particular specialized variety of > programs that are designed to operate with whatever hardware is built into > the target system. > > The advantage of using C on many such systems isn't that one can simply grab > arbitrary bits of code from here and there and run it, but rather that a > programmer who wants to turn on a light need only worry about: > > 1. Which I/O port is the light hooked up to > > 2. Which bits of which addresses need to be written to activate that > port > There are a good many other advantages in using C (compared to assembly, which I think was implied by you). But I agree that one would not expect to take arbitrary existing C code and find it useful on a small microcontroller. > Rather than also having to worry about the sequence of instructions that > might be needed to perform such an access, any restrictions that might exist > regarding the placement of such code and any data it requires, and also the > question of what one must do to ensure that code gets put into whatever kind > of code section is required on the target. The placement of the light and > the sequence of accesses needed to activate it will vary depending upon the > hardware platform, but there's no reason the syntax for performing such > accesses should need to. >
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-04-17 09:38 -0700 |
| Message-ID | <7e0dafe6-94d0-4e81-b3f8-7112b639f1f4@googlegroups.com> |
| In reply to | #108213 |
On Monday, April 17, 2017 at 11:08:36 AM UTC-5, David Brown wrote: > On 14/04/17 20:57, supercat wrote: > > I've not had problems with the const-pointer treatment breaking code; I'm > > not sure how much otherwise-usable code would be broken by it. On many > > parts, the difference in RAM and ROM sizes is sufficiently large (30:1 or > > more) that a lot of programs would be nowhere close to being able to store > > all their tables in RAM, but would still be nowhere near filling their code > > space. > > If you haven't used a compiler where turning a non-const pointer into a > const pointer breaks things, then of course you won't have had problems > with it. Most compilers are perfectly happy with such conversions. On the PIC compilers, turning a non-const pointer into a const pointer is not a problem, it is the reverse which is problematic. I make no effort to justify any C dialect which can't accommodate non-const to const conversions. > > On the PIC compilers, that will work without difficulty. The act of reading > > a const pointer causes the compiler to check a bit in the pointer and either > > access RAM or ROM. The situations the PIC has trouble with are using non- > > const pointers to read const data, or round-tripping const pointers through > > non-const pointers, but of which are much rarer than using const pointers to > > read both const and non-const data. > > Those will be rarer situations, but may still mean legal code will fail. Of course, requiring that all data be kept in RAM would mean that legal code whose tables won't fit in RAM will fail. No compiler for a system with 192 bytes of RAM is going to be able to handle all code that should be legal. Various compiler designs which forego the ability to run some should-be-legal program may pick up the ability to run some others. > > The reason I regard the > > PIC's behavior as somewhat reasonable [albeit obviously non-conforming] is > > that it allows many programs to run efficiently without modification in a > > way which would not be possible had another keyword been chosen. > > I agree that such behaviour is "somewhat reasonable". I'd much prefer a > command line switch, however. Okay, I think our main point of divergence was that we were talking about two different compilers' behaviors; I was insisting that the behavior I was talking about was "somewaht reasonable", and you apparently agree; you were insisting that the behavior you were talking about was unreasonable, and I agree. I had been unaware that any compilers behaved as you described, and you had been unaware that any behave as I describe, so now we both know of another pattern that some compilers use.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-04-12 18:13 -0700 |
| Message-ID | <lntw5tun1p.fsf@kst-u.example.com> |
| In reply to | #108083 |
David Brown <david.brown@hesbynett.no> writes:
> On 11/04/17 17:37, supercat@casperkitty.com wrote:
>> On Tuesday, April 11, 2017 at 4:33:26 AM UTC-5, David Brown wrote:
>>> On 11/04/17 00:43, supercat wrote:
>>>> On Monday, April 10, 2017 at 5:18:39 PM UTC-5, David Brown wrote:
>>>> I don't think the Standard allows compilers to regard as Undefined Behavior
>>>> the use of any entry-function signature other than those explicitly described.
>>>> If an implementation that didn't describe any behavior for "void main()"
>>>> would be allowed to treat it as UB, I see no reason that it shouldn't be
>>>> allowed to describe a useful behavior that differs from "int main()".
>>>>
>>>
>>> I can't figure out what you are trying to say here. We are not talking
>>> about undefined behaviour here - we are talking about a non-conforming
>>> implementation of the compiler.
>>
>> If some compiler X doesn't document any particular behavior for "void main()"
>> but such code happens to behave like "int main()" but without variable
>> initialization, such behavior would be conforming since use of "void main()"
>> would be UB, making all possible actions conforming.
>>
>> If some compiler Y were identical to X except that it *documented* that
>> "void main()" would work as it does in compiler X, then "void main()" would
>> not be UB on compiler Y, but I see no reason that compiler Y shouldn't be
>> conforming.
>
> You are still making no sense. The implementation's way of handling
> main() cannot be undefined behaviour - it is defined by the
> implementation. It might not conform to the C standards, but it can
> never be undefined behaviour.
The phrase "undefined behavior" is defined in C11 3.4.3 as:
behavior, upon use of a nonportable or erroneous program construct
or of erroneous data, for which this International Standard imposes
no requirements
In general, if a construct has undefined behavior and an implementation
chooses to define it, it still has "undefined behavior" by that
definition.
But the behavior of the program `void main(void){}` is not
(unconditionally) undefined. By 5.1.2.2.1, the main function may
be defined "... or in some other implementation-defined manner".
If the current implementation documents its support for `void
main(void(){/*...*/}`, then that's a permissible definition, and the
behavior is defined (but the termination status is unspecified).
If not, then the program violates a "shall" outside a constraint,
and its behavior is undefined.
Note that for an implementation that documents that it supports `void
main(void)`, all the requirements in the standard (aside from the
termination status) are in full force. Omitting zero-initialization of
static objects would still make the implementation non-conforming.
I suppose a implementation could (a) *not* document `void main(void)`
as "some other implementation-defined manner" under 5.1.2.2.1, but
(b) document `void main(void)` as an extension under 4p6, and then
do anything it likes. But that would be perverse.
An implementation can certainly support an extension that
doesn't zero-initialize static objects, as long as that extension
doesn't break any strictly conforming program. For example, a
compiler-specific #pragma would be OK. Triggering the behavior
based on the return type of main would IMHO be silly.
(Note that `main` is relevant only for hosted implementations.)
[...]
> I agree that for some targets, it can be better to make some breakage to
> C standards conformity. But that should be kept to the absolute
> minimum, be well documented, not break working code silently, and
> preferably require a command-line switch to activate it or give warnings
> about the odd behaviour. It is reasonable, for example, for a C
> implementation on a small 8-bit micro to make "double" limited to 32
> bits. It is /not/ reasonable to change the meaning of a keyword like
> "const" to mean something subtly different, or to skip the zeroing of
> uninitialised data.
Wouldn't it be better to support 32-bit "float" and reject "double"?
It's non-conforming either way, but it would cleanly reject code that
uses "double" and quite reasonably expects it to be wider than 32
bits.
[...]
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-04-13 07:37 -0700 |
| Message-ID | <45db5042-80fe-4900-9724-1bf2e3f7092c@googlegroups.com> |
| In reply to | #108093 |
On Wednesday, April 12, 2017 at 8:14:05 PM UTC-5, Keith Thompson wrote: > Wouldn't it be better to support 32-bit "float" and reject "double"? > It's non-conforming either way, but it would cleanly reject code that > uses "double" and quite reasonably expects it to be wider than 32 > bits. The Standard specifies that arguments to variadic functions get converted to type "double". The Standard provides a means by which implementations can report the level of precision that their "double" types support, but specifies a minimum which requires using longer than a 32-bit significand.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-04-13 08:43 -0700 |
| Message-ID | <lnh91suxd5.fsf@kst-u.example.com> |
| In reply to | #108104 |
supercat@casperkitty.com writes:
> On Wednesday, April 12, 2017 at 8:14:05 PM UTC-5, Keith Thompson wrote:
>> Wouldn't it be better to support 32-bit "float" and reject "double"?
>> It's non-conforming either way, but it would cleanly reject code that
>> uses "double" and quite reasonably expects it to be wider than 32
>> bits.
>
> The Standard specifies that arguments to variadic functions get converted
> to type "double".
That's a good point. On the other hand, it might not apply to the tiny
8-bit system being discussed. I don't know whether it supports printf,
or specifically printf for floating-point types.
> The Standard provides a means by which implementations
> can report the level of precision that their "double" types support, but
> specifies a minimum which requires using longer than a 32-bit significand.
True, but we're talking about a non-conforming implementation. The
question is which violation is better: making double 32 bits, or not
supporting double at all. The assumption is that the target supports
32-bit floating-point, but nothing wider (and it's not worthwhile to
support wider floating-point in software).
You can make double 32 bits, or you can drop support for double, change
the promotion rules, and change the type of floating-point constants.
Perhaps making double 32 bits is less intrusive.
And if you make double 32 bits, what about long double?
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-04-13 11:24 -0700 |
| Message-ID | <bec09399-174b-451b-a4b8-d846b1e80ced@googlegroups.com> |
| In reply to | #108105 |
On Thursday, April 13, 2017 at 10:43:39 AM UTC-5, Keith Thompson wrote: > That's a good point. On the other hand, it might not apply to the tiny > 8-bit system being discussed. I don't know whether it supports printf, > or specifically printf for floating-point types. The Hi-Tech compilers for the PIC have a library option to include one of three different versions of printf; the fanciest one supports floating-point (using 32-bit "double") but the code space required for that printf function by itself would exceed the storage capacity of the smaller chips. > > > The Standard provides a means by which implementations > > can report the level of precision that their "double" types support, but > > specifies a minimum which requires using longer than a 32-bit significand. > > True, but we're talking about a non-conforming implementation. The > question is which violation is better: making double 32 bits, or not > supporting double at all. The assumption is that the target supports > 32-bit floating-point, but nothing wider (and it's not worthwhile to > support wider floating-point in software). Some platforms have a 32-bit FPU but nothing wider; others have no FPU and must do everything in software. > You can make double 32 bits, or you can drop support for double, change > the promotion rules, and change the type of floating-point constants. > Perhaps making double 32 bits is less intrusive. Having DBL_DIG be quantitatively smaller than the value given in the Standard would make an implementation non-conforming (IMHO, that should have been a QoI issue, given that code which needs any particular level of precision could test for it) but having floating-point values passed to variadic functions as a type incompatible with "double" would be qualitatively wrong. Personally, I think systems without floating-point units should use 40- or 48-bit computational types with a 31-bit or 32-bit significand, and think it unfortunate that the Standard would not have allowed implementations to use such a type as "double". On 16-bit or 32-bit platforms, such a type could be processed just as cheaply as an IEEE single, and even on 8-bit platforms the cost wouldn't increase too badly. Going beyond a 32-bit significand represents a big increase in computational cost on any system which does not have hardware support for a larger type, but for many applications the benefits of going beyond 32 bits would be far smaller than the benefits of going from 24 to 32. > And if you make double 32 bits, what about long double? Also 32 bits; if a project is going to include library code to handle wider types, that code might as well be used for "double".
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-04-13 11:49 -0700 |
| Message-ID | <lnd1cguoqn.fsf@kst-u.example.com> |
| In reply to | #108106 |
supercat@casperkitty.com writes:
> On Thursday, April 13, 2017 at 10:43:39 AM UTC-5, Keith Thompson wrote:
[...]
>> You can make double 32 bits, or you can drop support for double, change
>> the promotion rules, and change the type of floating-point constants.
>> Perhaps making double 32 bits is less intrusive.
>
> Having DBL_DIG be quantitatively smaller than the value given in the
> Standard would make an implementation non-conforming (IMHO, that should have
> been a QoI issue, given that code which needs any particular level of
> precision could test for it) but having floating-point values passed to
> variadic functions as a type incompatible with "double" would be
> qualitatively wrong.
Hmm. I'd say non-conformance is non-conformance. Once you start
down that road, the main consideration should probably be programmer
convenience. (There should be a fairly high barrier to breaking
conformance in the first place; I'd rather have a conforming
implementation unless there's a *very* good reason not to.)
> Personally, I think systems without floating-point units should use 40- or
> 48-bit computational types with a 31-bit or 32-bit significand, and think
> it unfortunate that the Standard would not have allowed implementations to
> use such a type as "double".
Are you sure it doesn't? The standard doesn't require double to be 64
bits. It requires DBL_DECIMAL_DIG to be at least 10 (that's about 34
bits) with a decimal exponent range of at least +/-37 (about 7 bits
including the exponent sign). I don't think you could satisfy that in
40 bits, but I think 48 would be plenty. This is a back-of-the-envelope
estimate, and there could be several off-by-one errors; perhaps someone
else could check this.
[...]
>> And if you make double 32 bits, what about long double?
>
> Also 32 bits; if a project is going to include library code to handle
> wider types, that code might as well be used for "double".
Type double is special, since it's the type of unsuffixed floating
constants and the promoted type for variadic functions. But long double
has no such special role, and any code that uses it is probably
depending on it to have extra range and/or precision. Rejecting any use
of "long double", it seems to me, would be a better way to warn the you
that the target system doesn't support what you're asking for.
On the other hand, I don't program for such systems, and the opinions of
those who do should count more than mine.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Robert Wessel <robertwessel2@yahoo.com> |
|---|---|
| Date | 2017-04-13 14:43 -0500 |
| Message-ID | <mvkvecdig9sugrk07vtqjabov9hu68j6u3@4ax.com> |
| In reply to | #108107 |
On Thu, 13 Apr 2017 11:49:36 -0700, Keith Thompson <kst-u@mib.org> wrote: >supercat@casperkitty.com writes: > >> Personally, I think systems without floating-point units should use 40- or >> 48-bit computational types with a 31-bit or 32-bit significand, and think >> it unfortunate that the Standard would not have allowed implementations to >> use such a type as "double". > >Are you sure it doesn't? The standard doesn't require double to be 64 >bits. It requires DBL_DECIMAL_DIG to be at least 10 (that's about 34 >bits) with a decimal exponent range of at least +/-37 (about 7 bits >including the exponent sign). I don't think you could satisfy that in >40 bits, but I think 48 would be plenty. This is a back-of-the-envelope >estimate, and there could be several off-by-one errors; perhaps someone >else could check this. He's suggesting that the mantissa be limited to ~32 bits, so as to make it easy to implement on small systems. IOW, ones that can handle 32 bit *integers* with reasonable performance, could likely handle a 32 bit in a straight-forward manner, and without special hardware. I believe the requirements of DBL_DECIMAL_DIG make that impossible.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-04-13 13:26 -0700 |
| Message-ID | <553ef5ed-4d49-4fed-899f-74f7852c7ad5@googlegroups.com> |
| In reply to | #108108 |
On Thursday, April 13, 2017 at 2:43:31 PM UTC-5, robert...@yahoo.com wrote: > He's suggesting that the mantissa be limited to ~32 bits, so as to > make it easy to implement on small systems. IOW, ones that can handle > 32 bit *integers* with reasonable performance, could likely handle a > 32 bit in a straight-forward manner, and without special hardware. I > believe the requirements of DBL_DECIMAL_DIG make that impossible. Bingo. A 16-bit or 32-bit processor can handle a 32-bit mantissa as cheaply as a 24-bit one, and a 64-bit mantissa as cheaply as a 53-bit one. On an 8- bit system, when writing in machine code, the cost of a 40-bit mantissa would not be terribly much greater than that of 32 bits, but using 32 bits would allow some floating-point library functions to be written in C, using the "unsigned long" type.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-04-13 13:32 -0700 |
| Message-ID | <ln8tn4ujz9.fsf@kst-u.example.com> |
| In reply to | #108108 |
Robert Wessel <robertwessel2@yahoo.com> writes:
> On Thu, 13 Apr 2017 11:49:36 -0700, Keith Thompson <kst-u@mib.org>
> wrote:
>>supercat@casperkitty.com writes:
>>> Personally, I think systems without floating-point units should use 40- or
>>> 48-bit computational types with a 31-bit or 32-bit significand, and think
>>> it unfortunate that the Standard would not have allowed implementations to
>>> use such a type as "double".
>>
>>Are you sure it doesn't? The standard doesn't require double to be 64
>>bits. It requires DBL_DECIMAL_DIG to be at least 10 (that's about 34
>>bits) with a decimal exponent range of at least +/-37 (about 7 bits
>>including the exponent sign). I don't think you could satisfy that in
>>40 bits, but I think 48 would be plenty. This is a back-of-the-envelope
>>estimate, and there could be several off-by-one errors; perhaps someone
>>else could check this.
>
> He's suggesting that the mantissa be limited to ~32 bits, so as to
> make it easy to implement on small systems. IOW, ones that can handle
> 32 bit *integers* with reasonable performance, could likely handle a
> 32 bit in a straight-forward manner, and without special hardware. I
> believe the requirements of DBL_DECIMAL_DIG make that impossible.
I believe you're right. A conforming 48-bit double is possible, but a
conforming 48-bit double with a 32-bit significand is not.
I can see the advantage of allowing more flexibility for floating-point
types, particularly for freestanding implementations. I doubt that such
flexibility would be particularly useful for hosted implementations.
On the other hand, implementations already have as much flexibility as
they need if they don't claim ISO C conformance. One approach is to
implement as much of ISO C as practical and *clearly* document any
exceptions. Features that might reasonably be omitted include
floating-point wider than 32 bits, *all* floating-point, and 64-bit
integers. The question (well, *a* question) is whether it's worthwhile
to have the standard explictly permit such omissions.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-04-13 14:27 -0700 |
| Message-ID | <d02c342f-9098-4091-9699-d27d1fc895d5@googlegroups.com> |
| In reply to | #108111 |
On Thursday, April 13, 2017 at 3:32:44 PM UTC-5, Keith Thompson wrote: > On the other hand, implementations already have as much flexibility as > they need if they don't claim ISO C conformance. One approach is to > implement as much of ISO C as practical and *clearly* document any > exceptions. Features that might reasonably be omitted include > floating-point wider than 32 bits, *all* floating-point, and 64-bit > integers. The question (well, *a* question) is whether it's worthwhile > to have the standard explictly permit such omissions. Indeed. Another feature that is sometimes omitted in the absence of special compiler options is support for recursive function calls. While that is in some ways a limitation, it allows the linker to reject programs whose automatic variable usage would overflow the stack, rather than having such programs crash at runtime. Presently, the Standard does not specify anything useful about what level of nested subroutine calls an implementation must support, nor about what may happen if code goes beyond that. It also does not specify what level of nesting may be used in a Strictly Conforming program. Consequently, the question of whether an implementation can execute a given Strictly Conforming Program without jumping the rails is a "quality-of-implementation" issue. I would suggest that the question of which programs an implementation can *usefully* process should be a QoI issue, but anything worthy of being called a "standard" should define categories of implementations and programs such that behavior would always be at least loosely defined (chosen in Unspecified fashion from Implementation-Defined alternatives) provided Implementation- Defined environmental requirements are satisfied. Having an implementation be able to usefully run a wide range of programs is helpful, but a guarantee that it will reject any programs it can't run usefully would be even better.
[toc] | [prev] | [next] | [standalone]
| From | Robert Wessel <robertwessel2@yahoo.com> |
|---|---|
| Date | 2017-04-13 17:39 -0500 |
| Message-ID | <qquvec55unjf78a6ogiob2rjcv02ve4984@4ax.com> |
| In reply to | #108112 |
On Thu, 13 Apr 2017 14:27:50 -0700 (PDT), supercat@casperkitty.com wrote: >On Thursday, April 13, 2017 at 3:32:44 PM UTC-5, Keith Thompson wrote: >> On the other hand, implementations already have as much flexibility as >> they need if they don't claim ISO C conformance. One approach is to >> implement as much of ISO C as practical and *clearly* document any >> exceptions. Features that might reasonably be omitted include >> floating-point wider than 32 bits, *all* floating-point, and 64-bit >> integers. The question (well, *a* question) is whether it's worthwhile >> to have the standard explictly permit such omissions. > >Indeed. Another feature that is sometimes omitted in the absence of >special compiler options is support for recursive function calls. While >that is in some ways a limitation, it allows the linker to reject programs >whose automatic variable usage would overflow the stack, rather than having >such programs crash at runtime. > >Presently, the Standard does not specify anything useful about what level of >nested subroutine calls an implementation must support, nor about what may >happen if code goes beyond that. It also does not specify what level of >nesting may be used in a Strictly Conforming program. Consequently, the >question of whether an implementation can execute a given Strictly Conforming >Program without jumping the rails is a "quality-of-implementation" issue. > >I would suggest that the question of which programs an implementation can >*usefully* process should be a QoI issue, but anything worthy of being called >a "standard" should define categories of implementations and programs such >that behavior would always be at least loosely defined (chosen in Unspecified >fashion from Implementation-Defined alternatives) provided Implementation- >Defined environmental requirements are satisfied. Having an implementation >be able to usefully run a wide range of programs is helpful, but a guarantee >that it will reject any programs it can't run usefully would be even better. The issue of whether or not recursion is supported is separate from the one regarding available "stack" space. Some small systems do not support stack-based allocation in a convenient way, and compilers tend to generate all local variables equivalent to C statics. Such an implementation would likely not support recursion. Only in the case of a program with no recursion, no function pointers no VLAs, no alloca, complete source visibility, etc., can the compiler generally make a compile time determination of stack usage (although some simple cases involving those would be amenable to analysis). Removing recursion from the list doesn't solve the problem. Some sort of runtime mechanism is likely needed if applications are going to deal with "stack" overflow. *"stack" used above in the sense of a LIFO structure, not specifically a hardware stack.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-04-13 16:16 -0700 |
| Message-ID | <3543d2a1-0629-4737-a97f-80d44ca87918@googlegroups.com> |
| In reply to | #108113 |
On Thursday, April 13, 2017 at 5:39:20 PM UTC-5, robert...@yahoo.com wrote:
> Only in the case of a program with no recursion, no function pointers
> no VLAs, no alloca, complete source visibility, etc., can the compiler
> generally make a compile time determination of stack usage (although
> some simple cases involving those would be amenable to analysis).
> Removing recursion from the list doesn't solve the problem. Some sort
> of runtime mechanism is likely needed if applications are going to
> deal with "stack" overflow.
Compilers I've used on the PIC and 8051 both required that compilers supply
information about automatic variable usage and called functions to the linker,
which could then build a call graph. A call to a function pointer of a given
type was regarded as a potential call to every compatible function whose
address had been taken. I don't remember whether the 8051 call graph counted
any temporary variables the compiler pushed on the hardware stack, but then
again I don't remember whether it ever actually used any. On the PIC, if the
total depth of the main line and interrupt call stacks was below the hardware
stack limit, a stack overflow couldn't happen.
If compilers for other platforms included similar logic and built upon it
slightly, it would be possible for languages to allow recursion while
allowing static validation of stack usage if the language included a
"__stack_safe" intrinsic which would return 0 unless the it could statically
guarantee stack safety when it returned 1. This would require that the
object file format allow functions to say, e.g.
When all __stack_space calls return returns 0:
Calls foo with 32 bytes on the stack
Calls bar with 68 bytes on the stack
Puts 192 bytes on the stack when not calling anything
When __stack_space check #1 returns 1:
Calls foo with 32 bytes on the stack
Calls bar with 68 bytes on the stack
Calls boz with 96 bytes on the stack
Puts 192 bytes on the stack when not calling anything
When __stack_space check #2 returns 2:
Calls moo with 48 bytes on the stack
Calls boz with 96 bytes on the stack
Puts 192 bytes on the stack when not calling anything
A linker could then compute how much space would need to be available on
the stack to allow any function to be called *safely*, and also compute
for each __stack_space check how much stack space would need to be available
to allow it to safely return 1. Programs could safely use recursion without
risk of stack overflow if there were at least one __stack_space check on any
recursive path, and there would be no need for any implementation-specific
measures of stack capacity. Provided that the linker were informed of the
worst-case stack usage for things like interrupts, assembly-language
functions, etc. it should be possible and practical to statically verify
stack usage without having to artificially constrain the depth of recursion
that could be used for things like structure parsing.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2017-04-16 17:53 -0700 |
| Message-ID | <kfninm397nh.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #108108 |
Robert Wessel <robertwessel2@yahoo.com> writes: > On Thu, 13 Apr 2017 11:49:36 -0700, Keith Thompson <kst-u@mib.org> > wrote: > >> supercat@casperkitty.com writes: >> >>> Personally, I think systems without floating-point units should use 40- or >>> 48-bit computational types with a 31-bit or 32-bit significand, and think >>> it unfortunate that the Standard would not have allowed implementations to >>> use such a type as "double". >> >> Are you sure it doesn't? The standard doesn't require double to be 64 >> bits. It requires DBL_DECIMAL_DIG to be at least 10 (that's about 34 >> bits) with a decimal exponent range of at least +/-37 (about 7 bits >> including the exponent sign). I don't think you could satisfy that in >> 40 bits, but I think 48 would be plenty. This is a back-of-the-envelope >> estimate, and there could be several off-by-one errors; perhaps someone >> else could check this. > > He's suggesting that the mantissa be limited to ~32 bits, so as to > make it easy to implement on small systems. IOW, ones that can handle > 32 bit *integers* with reasonable performance, could likely handle a > 32 bit in a straight-forward manner, and without special hardware. I > believe the requirements of DBL_DECIMAL_DIG make that impossible. Right. The minumum value for DBL_DECIMAL_DIG implies that just over 33 bits are needed (and that's for a decimal base - the number of bits needed is higher for any non-power-of-10 base).
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-04-13 13:19 -0700 |
| Message-ID | <562a9c9f-9b79-43f7-a377-32c251c359ec@googlegroups.com> |
| In reply to | #108107 |
On Thursday, April 13, 2017 at 1:49:45 PM UTC-5, Keith Thompson wrote:
> > On Thursday, April 13, 2017 at 10:43:39 AM UTC-5, Keith Thompson wrote:
> [...]
> >> You can make double 32 bits, or you can drop support for double, change
> >> the promotion rules, and change the type of floating-point constants.
> >> Perhaps making double 32 bits is less intrusive.
> >
> > Having DBL_DIG be quantitatively smaller than the value given in the
> > Standard would make an implementation non-conforming (IMHO, that should have
> > been a QoI issue, given that code which needs any particular level of
> > precision could test for it) but having floating-point values passed to
> > variadic functions as a type incompatible with "double" would be
> > qualitatively wrong.
>
> Hmm. I'd say non-conformance is non-conformance. Once you start
> down that road, the main consideration should probably be programmer
> convenience. (There should be a fairly high barrier to breaking
> conformance in the first place; I'd rather have a conforming
> implementation unless there's a *very* good reason not to.)
Floating-point libraries tend to be code hogs; code which supported a minimal
conforming "double" and was only twice as slow for addition would likely need
to be about twice as big as code for an IEEE single. Actually, some low-end
compilers have an option to pare floating-point types back to a 16-bit
significand (for double as well as float), and by my understanding such
options are used fairly often, given the savings in code size and execution
time.
> > Personally, I think systems without floating-point units should use 40- or
> > 48-bit computational types with a 31-bit or 32-bit significand, and think
> > it unfortunate that the Standard would not have allowed implementations to
> > use such a type as "double".
>
> Are you sure it doesn't? The standard doesn't require double to be 64
> bits. It requires DBL_DECIMAL_DIG to be at least 10 (that's about 34
> bits) with a decimal exponent range of at least +/-37 (about 7 bits
> including the exponent sign). I don't think you could satisfy that in
> 40 bits, but I think 48 would be plenty. This is a back-of-the-envelope
> estimate, and there could be several off-by-one errors; perhaps someone
> else could check this.
For performance, the key on 16-bit and larger systems is to keep the
significand to 32 bits or less, which is good for 7-9 digits. A 40-bit
significand would be adequate, and could easily fit in a 48-bit type,
but on 16-bit and 32-bit platforms it would cost just as much to process
as a 48-bit significand.
> >> And if you make double 32 bits, what about long double?
> >
> > Also 32 bits; if a project is going to include library code to handle
> > wider types, that code might as well be used for "double".
>
> Type double is special, since it's the type of unsuffixed floating
> constants and the promoted type for variadic functions. But long double
> has no such special role, and any code that uses it is probably
> depending on it to have extra range and/or precision. Rejecting any use
> of "long double", it seems to me, would be a better way to warn the you
> that the target system doesn't support what you're asking for.
It's possible the compiler rejects "long double". The behavior of floating-
point types was sufficiently-poorly specified that it's unclear what any
particular authors means when using that type. The purpose for which the
IEEE extended type was created was to serve as a temporary computation type
for use within expressions, but if a programmer wants to use manual common
sub-expression elimination it's necessary to have a type that can be used to
represent temporaries. For example, if programmer wants to manually remove
the redundant computation of (a+b) in
double a,b,c1,c2; // Assign values somehow
double x = a+b+c1;
double y = a+b+c2;
on a system which uses an extended-precision temporary type, the proper way
to do that on a system where FLT_EVAL_METHOD==2 would be:
double a,b,c1,c2; // Assign values somehow
long double temp=a+b;
double x = temp+c1;
double y = temp+c2;
Note that what the code really needs is not that "temp" have any particular
level of precision, but rather that it be capable of holding the temporary
result "a+b" with the same precision as it would have within a larger
expression. If the authors of the Standard had specified that all floating-
point arguments, including "long double" will be passed as "double" except
in cases where there exists a prototype or the argument is a cast expression,
the "long double" type would probably have been a lot more popular since
all of:
printf("%10.5f", expressionYieldingDouble);
printf("%10.5f", expressionYieldingLongDouble);
printf("%10.5Lf", (long double)expressionYieldingDouble);
printf("%10.5Lf", (long double)expressionYieldingLongDouble);
would behave sensibly (the second line might not produce optimal precision,
but in most cases would be adequate).
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2017-04-16 17:49 -0700 |
| Message-ID | <kfnmvbf97tu.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #108107 |
Keith Thompson <kst-u@mib.org> writes: >> [..question about size needed for floating-point types..] > > [...] The standard doesn't require double to be 64 > bits. It requires DBL_DECIMAL_DIG to be at least 10 (that's about 34 > bits) with a decimal exponent range of at least +/-37 (about 7 bits > including the exponent sign). I don't think you could satisfy that in > 40 bits, but I think 48 would be plenty. This is a back-of-the-envelope > estimate, and there could be several off-by-one errors; perhaps someone > else could check this. Right, 40 bits is not enough to satisfy the Standard's minimum requirements for double. It is just barely enough if a sign bit is not needed, but taking negative numbers into account pushes the minimum up to 41 bits. (And that bound holds only for representations that use a decimal base.)
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-04-17 18:14 +0200 |
| Message-ID | <od2pfp$15a$1@dont-email.me> |
| In reply to | #108105 |
On 13/04/17 17:43, Keith Thompson wrote: > supercat@casperkitty.com writes: >> On Wednesday, April 12, 2017 at 8:14:05 PM UTC-5, Keith Thompson wrote: >>> Wouldn't it be better to support 32-bit "float" and reject "double"? >>> It's non-conforming either way, but it would cleanly reject code that >>> uses "double" and quite reasonably expects it to be wider than 32 >>> bits. >> >> The Standard specifies that arguments to variadic functions get converted >> to type "double". > > That's a good point. On the other hand, it might not apply to the tiny > 8-bit system being discussed. I don't know whether it supports printf, > or specifically printf for floating-point types. It is not uncommon in development tools for small microcontrollers to have limited or missing support for printf of floating point types, or to make such support optional (since it will make the printf function significantly bigger, even if the feature is not used by the program). > >> The Standard provides a means by which implementations >> can report the level of precision that their "double" types support, but >> specifies a minimum which requires using longer than a 32-bit significand. > > True, but we're talking about a non-conforming implementation. The > question is which violation is better: making double 32 bits, or not > supporting double at all. The assumption is that the target supports > 32-bit floating-point, but nothing wider (and it's not worthwhile to > support wider floating-point in software). Yes, that's the issue. > > You can make double 32 bits, or you can drop support for double, change > the promotion rules, and change the type of floating-point constants. > Perhaps making double 32 bits is less intrusive. That is the most common opinion. > > And if you make double 32 bits, what about long double? > Typically, it is non-existant. There are a good many embedded development tools where the support for C99 is limited, and this is a common limitation.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-04-17 11:54 -0700 |
| Message-ID | <lnr30qsw44.fsf@kst-u.example.com> |
| In reply to | #108216 |
David Brown <david.brown@hesbynett.no> writes:
> On 13/04/17 17:43, Keith Thompson wrote:
[...]
>> And if you make double 32 bits, what about long double?
>
> Typically, it is non-existant. There are a good many embedded
> development tools where the support for C99 is limited, and this is a
> common limitation.
This isn't the first time I've seen the incorrect idea that long double
was added in C99. In fact it existed in C89/C90. (C99 did add <math.h>
functions for float and long double; C90's <math.h> only provided
functions for double.) The ANSI C Rationale mentions "long double" as a
new type.
Still, dropping long double for a *non-conforming* compiler for a small
embedded system is likely to be a good idea.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-04-17 22:41 +0200 |
| Message-ID | <od394b$o7l$1@dont-email.me> |
| In reply to | #108237 |
On 17/04/17 20:54, Keith Thompson wrote: > David Brown <david.brown@hesbynett.no> writes: >> On 13/04/17 17:43, Keith Thompson wrote: > [...] >>> And if you make double 32 bits, what about long double? >> >> Typically, it is non-existant. There are a good many embedded >> development tools where the support for C99 is limited, and this is a >> common limitation. > > This isn't the first time I've seen the incorrect idea that long double > was added in C99. In fact it existed in C89/C90. (C99 did add <math.h> > functions for float and long double; C90's <math.h> only provided > functions for double.) The ANSI C Rationale mentions "long double" as a > new type. Really? That is news to me - but then, I come here to learn! The only compilers I have used that have supported long double have been those with good C99 support (like gcc, Code Warrior, Green Hills, and a few others) - while those with little or no C99 support invariably have no long doubles either. > > Still, dropping long double for a *non-conforming* compiler for a small > embedded system is likely to be a good idea. > Indeed. For most tools for small microcontrollers, that sort of non-conformity is to be expected. And no one (or very few people) are going to miss long double support on their 8 bit microcontrollers.
[toc] | [prev] | [next] | [standalone]
Page 2 of 3 — ← Prev page 1 [2] 3 Next page →
Back to top | Article view | comp.lang.c
csiph-web