Topic: negative integer literals
Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/04/09 Raw View
X-Auth: PGPMoose V1.1 PGP comp.std.c++
iQBVAwUBM0wbnEy4NqrwXLNJAQH60wIAmUP0M3Vm4kA1qHL4kiSPyMqNpl8vkuKl
o5RwdFpJcpiO2SA+x12YH2bZ8I3vekmY4kP8jUhmmqkE+LslSplIMA==
=86IB
James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:
>fjh@mundook.cs.mu.OZ.AU (Fergus Henderson) writes:
>
>There is obviously a quality of implementation issue involved, but it is
>a very poor choice to activate extensions automatically. If I
>accidentally type "long long", my program shouldn't compile *UNLESS*
>I've specified that I want the extension.
Sure, it is a quality of implementation issue as to whether it is
better to issue warnings or errors in such cases. Which is better
may depend on the situation, so perhaps it is best to leave the
choice up to the user, as g++ does: with g++, you can choose between
`-pedantic' and `-pedantic-errors'.
>|> For a program that contains `long long', after issuing a diagnostic,
>|> the compiler is free to choose whatever semantics it likes. However,
>|> for a program that does not contain `long long', but does contain a
>|> literal that will fit in `unsigned long' but not in `long', e.g.
>|> 2147483648, the DWP specifies the semantics, and a conforming compiler
>|> is _not_ free to make the type of such literals `long long'.
>
>Correct. Presumably, to be useful, such a compiler will have two modes,
>one which accepts long long, and handles type promotion correctly for
>that case, and another which doesn't, and handles type promotion
>correctly for C++. While I would consider it a very bad choice, I
>suppose that a compiler could select the "long long" accepting mode
>automatically (after issuing a diagnostic) if the program contained
>"long long", and the normal most otherwise.
Unfortunately this is quite difficult to implement, and perhaps
impossible to implement efficiently -- it requires a prepass of the
whole program to see whether it contains "long long" before doing
semantic analysis or code generation.
>I believe that g++'s policy is to have the extensions active by default;
I agree this is a poor policy.
>|> In that case, it wouldn't be a true extension, because you would be
>|> changing the semantics of the base language.
>
>OK. I can buy this. Two points, however:
>
>1. Are you saying that C++ should adapt rules to facilitate such
>extensions?
I'm saying that
(a) the g++ decision to not change to promotion rules
when adding `long long' is a reasonable one
(because changing promotion rules might break existing code,
if compiled with extensions enabled);
(b) given (a), the sample program fragment
long long int = -2147483648;
does not give desired results;
(c) hence the way negative literals are handled in C++ at the moment
could cause problems in practice.
That's all I was trying to say.
In general I do think that all other things being equal, languages
should be designed to facilitate extensions. Of course other things
are never equal, so as always it is a matter of choosing appropriate
trade-offs.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: Neal Becker <neal@ctd.comsat.com>
Date: 1997/03/31 Raw View
>>>>> "James" == James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:
James> The problem is that the value of the expression -2147483648 is not
James> representable in a 32 bit signed int, since the value is the positive
James> number 2147483648. It would take some extremely tricky special case
James> wording to make it work.
I'm going out on a limb here since I haven't been following this
discussion. But with 2's complement arithmetic the range that is
represented by N bits is:
[-2^(N-1) ... 2^(N-1) - 1]. Inclusive.
So -2^(31) IS representable within a signed 32 bit integer!
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: James Kuyper <kuyper@wizard.net>
Date: 1997/04/01 Raw View
Neal Becker wrote:
>
> >>>>> "James" == James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:
>
> James> The problem is that the value of the expression -2147483648 is not
> James> representable in a 32 bit signed int, since the value is the
> James> positive number 2147483648. It would take some extremely tricky
> James> special case wording to make it work.
>
> I'm going out on a limb here since I haven't been following this
> discussion. But with 2's complement arithmetic the range that is
> represented by N bits is:
>
> [-2^(N-1) ... 2^(N-1) - 1]. Inclusive.
>
> So -2^(31) IS representable within a signed 32 bit integer!
Unfortunately, as this thread has discussed ad nauseum, according to the
C standard -2147483648 is not a negative integer literal with the value
of -2^31 (standard C doesn't have negative integer literals). Instead,
(in the 32 bit context assumed throughout this thread) it is a C
expression with the value 2147683648, which won't fit in a signed 32
bit integer. Some of us think this is a problem with the C standard,
though apparantly a difficult one to fix. See previous messages on this
thread for more details.
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/04/01 Raw View
fjh@mundook.cs.mu.OZ.AU (Fergus Henderson) writes:
|> James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:
|>
|> >Christopher Eltschka <celtschk@physik.tu-muenchen.de> writes:
|> >
|> >|> There can still be problems with this value:
|> >|> try f.ex. with gcc under Linux
|> >|>
|> >|> int i=-2147483648;
|> >|> assert(i<0); /* works */
|> >|>
|> >|> long long l=-2147483648;
|> >|> assert(l<0); /* fails */
|> >
|> >There is no "long long" type in C++, so this is a compiler extension.
|> >IMHO, if a compiler offers such an extension, it should also extend
|> >preprocessor arithmetic to cover the case. It would also seem natural
|> >that the implicit promotions take this into account, so that 2147483648
|> >would have type "long long", and the above would work.
|>
|> But if a compiler did that, then it would no longer be conforming.
Of course not. A compiler which accepts a program containing "long
long" is not conforming, period, regardless of what it does with its
constant expressions.
|> The standard specifies that integer literals that can fit into an unsigned
|> long but not a long should have type unsigned long. An extension
|> which gave such a value the type "long long" would not be a conforming
|> extension. I don't see how "implicit promotions" could fix this.
The standard also specifies that the sequence of tokens "long long" is a
syntax violation, which requires the compiler to issue a diagnostic.
I think that the extension is worthwhile. (Actually, I think it's a
hack, but for the point of argument...) But if you are adding integral
types, which can be used in constant integral expressions, you have to
redefine the promotion rules in some way anyway. What do you do if the
literal it too large to fit in an unsigned long?
In practice, such extensions should only be active if you have given a
specific option requesting them. If I request a long long type, I
certainly expect it to fit coherently into the type system, and give the
expected results. And if I don't request it (and I wouldn't unless I
needed it), then the sequence "long long" had better be a compiler
error, so there is no problem with regards to the type of the expression
which initializes it.
|> >This is all a quality of implementation issue however. The standard
|> >says nothing about long long.
|>
|> Yes, but it does place restrictions on what constitutes a conforming
|> extension, which constrain how a conforming implementation can implement
|> `long long'.
Yes. It says explicitly that a conforming implementation cannot
implement long long.
|> Hopefully C9X will change the rules when it adds `long long', so that
|> the code fragment above will work in conforming C9X implementations
|> (even though doing so would technically not be backwards compatible
|> with C89).
Agreed. Although I'm not sure that the new type will be spelled "long
long". (If so, where do we go from there? In another ten years, we'll
have "long long long", and then "long long long long", and then... But
that argument is for another thread, preferably in comp.std.c:-).)
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/04/01 Raw View
Neal Becker <neal@ctd.comsat.com> writes:
>>>>>> "James" == James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:
>
> James> The problem is that the value of the expression -2147483648 is not
> James> representable in a 32 bit signed int, since the value is the positive
> James> number 2147483648. It would take some extremely tricky special case
> James> wording to make it work.
>
>I'm going out on a limb here since I haven't been following this
>discussion. But [...]
>-2^(31) IS representable within a signed 32 bit integer!
James Kanze did not deny that the *number* -2^31 is representable in a
32 bit signed int. We're all aware of that. He said that the
*value of the expression* `-2147483648', namely the positive number
2147493648, is not representable in a 32 bit signed int.
Why is the value of the expression `-2147483648' a positive number?
Because `2147483648' is a literal of type `unsigned' (for the
implementations under discussion), and C++ defines unary minus on
unsigned integral types to return a value of the same unsigned integral
type.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/04/01 Raw View
Neal Becker <neal@ctd.comsat.com> writes:
|> >>>>> "James" == James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:
|>
|>
|> James> The problem is that the value of the expression -2147483648 is not
|> James> representable in a 32 bit signed int, since the value is the positive
|> James> number 2147483648. It would take some extremely tricky special case
|> James> wording to make it work.
|>
|> I'm going out on a limb here since I haven't been following this
|> discussion. But with 2's complement arithmetic the range that is
|> represented by N bits is:
|>
|> [-2^(N-1) ... 2^(N-1) - 1]. Inclusive.
|>
|> So -2^(31) IS representable within a signed 32 bit integer!
You're missing the context. The whole raison d'etre of this discussion
is that the constant expression -2147483648 is not an int, because it
requires an intermediate value (2147483648) which cannot be represented.
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/04/02 Raw View
X-Auth: PGPMoose V1.1 PGP comp.std.c++
iQBVAwUBM0KdcEy4NqrwXLNJAQHI4AH9G/uey/fgvl6q0AJREZj7hKZb/t2pzVbX
pfSKJeCSxAOPegUaDJbgO0xkUqWx/WzIcXrNXbbl60qxhIQec2xtrQ==
=zXke
James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:
>fjh@mundook.cs.mu.OZ.AU (Fergus Henderson) writes:
>
>|> James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:
>|>
>|> >There is no "long long" type in C++, so this is a compiler extension.
>|> >IMHO, if a compiler offers such an extension, it should also extend
>|> >preprocessor arithmetic to cover the case. It would also seem natural
>|> >that the implicit promotions take this into account, so that 2147483648
>|> >would have type "long long", and the above would work.
>|>
>|> But if a compiler did that, then it would no longer be conforming.
>
>Of course not. A compiler which accepts a program containing "long
>long" is not conforming, period, regardless of what it does with its
>constant expressions.
That's not correct. So long as the compiler issues a diagnostic,
it is then free to go ahead and accept the program. In fact,
that is exactly what g++ does in this case. When you invoke gcc
in pedantic mode, any use of `long long' will result in a warning.
>|> The standard specifies that integer literals that can fit into an unsigned
>|> long but not a long should have type unsigned long. An extension
>|> which gave such a value the type "long long" would not be a conforming
>|> extension. I don't see how "implicit promotions" could fix this.
>
>The standard also specifies that the sequence of tokens "long long" is a
>syntax violation, which requires the compiler to issue a diagnostic.
Yes; so?
For a program that contains `long long', after issuing a diagnostic,
the compiler is free to choose whatever semantics it likes. However,
for a program that does not contain `long long', but does contain a
literal that will fit in `unsigned long' but not in `long', e.g.
2147483648, the DWP specifies the semantics, and a conforming compiler
is _not_ free to make the type of such literals `long long'.
>I think that the extension is worthwhile. (Actually, I think it's a
>hack, but for the point of argument...) But if you are adding integral
>types, which can be used in constant integral expressions, you have to
>redefine the promotion rules in some way anyway. What do you do if the
>literal it too large to fit in an unsigned long?
Well, in that case the DWP says the program is ill-formed, so the compiler
must issue a diagnostic; but after that it has issued the diagnostic,
it can freely give the literal type `long long' and keep going.
>In practice, such extensions should only be active if you have given a
>specific option requesting them. If I request a long long type, I
>certainly expect it to fit coherently into the type system, and give the
>expected results.
Do you expect this even if doing so would violate standards conformance
for the subset which does _not_ use `long long'?
That might causes _other_ parts of your program, e.g. the header files
in some third-party library that you are using, to break, if they
relied on behaviour specified by the ANSI C standard and the C++ DWP.
In that case, it wouldn't be a true extension, because you would be
changing the semantics of the base language.
>|> >This is all a quality of implementation issue however. The standard
>|> >says nothing about long long.
>|>
>|> Yes, but it does place restrictions on what constitutes a conforming
>|> extension, which constrain how a conforming implementation can implement
>|> `long long'.
>
>Yes. It says explicitly that a conforming implementation cannot
>implement long long.
No, it does not. A conforming implementation certainly can implement
`long long'. For example, `gcc -ansi -pedantic' is (modulo bugs) a
conforming implementation, and it implements `long long'.
What the C standard (and similarly the C++ DWP) says implies that a
conforming implementation can implement `long long', but just not with the
rules for types of integral literals that you would like.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: Marcelo Cantos <marcelo@mds.rmit.edu.au>
Date: 1997/04/02 Raw View
James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:
> You're missing the context. The whole raison d'etre of this discussion
> is that the constant expression -2147483648 is not an int, because it
> requires an intermediate value (2147483648) which cannot be represented.
Has anyone noticed how annoying it is to discuss the number
2147483648? So much typing! (Or cutting and pasting.) I'm just glad
we had this discussion before 64-but ints became popular; we'd all be
busy bashing out the number 9223372036854775808; or worse still,
128-bit numbers (170141183460469231731687303715884105728)! :-) We'd
just about have to abandon 80-column displays for 256-bit numbers:
57896044618658097711785492504343953926634992332820282019728792003956564819968
(Now I'm being silly.)
Maybe we should mandate that public schools teach hexadecimal from now
on! Imagine having to learn the fifteen times tables!
PS: Please don't take this post seriously!! :-)
--
______________________________________________________________________
Marcelo Cantos, Research Assistant __/_ marcelo@mds.rmit.edu.au
Multimedia Database Systems Group, RMIT / _ Tel 61-3-9282-2497
723 Swanston St, Carlton VIC 3053 Aus/ralia ><_> Fax 61-3-9282-2490
Acknowledgements: errors - me; wisdom - God; funding - RMIT
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Ted Clancy <s341282%student.uq.edu.au.SPAM_REPELLENT@nac.no>
Date: 1997/04/06 Raw View
James Kanze wrote:
>
> willhall@idt.net (Will Hall) writes:
>
>
> I think that there could be a solution: it would represent a radical
> change in the way C/C++ has been described until now, but I don't think
> it would have much significant practical change (except to break
> programs which count on -2^31 being positive:-).)
>
> My idea would be that integer literals be untyped (but signed), and that
> the implementation be required to do integral constant arithmetic in
> "infinite" precision. (In practice, there must be implementation
> limits, but they should be required to be at least twice the number of
> bits in the largest integral type? or all values in the range
> LONG_MIN...ULONG_MAX?) Only when the integral literal is used does it
> aquire a type, according to its value and the context.
>
Sounds like a good idea, and not unlike what C++ already does for
expression &func, where func could be one of many overloaded functions.
In this case, &func doesn't have a type until it is assigned to a
variable, or passed to a function.
> This is trickier than it looks: there are several implications to be
> considered:
>
> 1. Function overloading. I don't think that there are any real problems
> here; the current rules are rather confusing anyway (the actual function
> depends on the value, and may change from one implementation to the
> next).
>
> 2. The use of the U and L suffixes. This is somewhat more difficult; if
> we don't want to break existing code, the presence of a suffix in the
> constant expression must constrain the type of the expression.
>
This could fit into C++ pretty well. Just consider constant integral
expressions to be of type CONSTEXP. The compiler defines
CONSTEXP operator+(CONSTEXP, CONSTEXP);
CONSTEXP operator-(CONSTEXP, CONSTEXP);
CONSTEXP operator-(CONSTEXP);
etc...
when a CONSTEXP is passed to a function, or used as an operand to
sizeof, its type would be the first of int, unsigned int, long, unsigned
long, which it can fit into, as is the current rule.
You could explicitly define
int operator+(int, CONSTEXP);
int operator-(int, CONSTEXP);
long operator+(long, CONSTEXP);
long operator-(long, CONSTEXP); //etc...
but these would probably be unnessary with the above rule, combined with
integral promotion.
The U and L suffixes can be treated as static_cast<unsigned>(CONSTEXP),
and static_cast<long>(CONSTEXP)
Of course, the time for additions has past, as you say. Maybe in the
next version of C++.
> --
> James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
> office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
> GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
> -- Conseils en informatique industrielle --
--
Ted Clancy, | Student of Engineering and Arts
s341282@student.uq.edu.au | Secretary of UQ-Trek
The University of Queensland. | The guy who hates macro NULL.
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/04/08 Raw View
fjh@mundook.cs.mu.OZ.AU (Fergus Henderson) writes:
|> James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:
|>
|> >fjh@mundook.cs.mu.OZ.AU (Fergus Henderson) writes:
|> >
|> >|> James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:
|> >|>
|> >|> >There is no "long long" type in C++, so this is a compiler extension.
|> >|> >IMHO, if a compiler offers such an extension, it should also extend
|> >|> >preprocessor arithmetic to cover the case. It would also seem natural
|> >|> >that the implicit promotions take this into account, so that 2147483648
|> >|> >would have type "long long", and the above would work.
|> >|>
|> >|> But if a compiler did that, then it would no longer be conforming.
|> >
|> >Of course not. A compiler which accepts a program containing "long
|> >long" is not conforming, period, regardless of what it does with its
|> >constant expressions.
|>
|> That's not correct. So long as the compiler issues a diagnostic,
|> it is then free to go ahead and accept the program. In fact,
|> that is exactly what g++ does in this case. When you invoke gcc
|> in pedantic mode, any use of `long long' will result in a warning.
So long as the compiler issues a diagnostic, it is also free to go ahead
and reformat your hard disk. (In comp.std.c, one person once suggested
that the documented diagnostic message could be that the compiler turns
on the light on the disk for 1 sec./Megabyte of storage:-).)
There is obviously a quality of implementation issue involved, but it is
a very poor choice to activate extensions automatically. If I
accidentally type "long long", my program shouldn't compile *UNLESS*
I've specified that I want the extension. (FWIW: in normal text,
doubling a word is one of the more frequent typing errors.)
|> >|> The standard specifies that integer literals that can fit into an unsigned
|> >|> long but not a long should have type unsigned long. An extension
|> >|> which gave such a value the type "long long" would not be a conforming
|> >|> extension. I don't see how "implicit promotions" could fix this.
|> >
|> >The standard also specifies that the sequence of tokens "long long" is a
|> >syntax violation, which requires the compiler to issue a diagnostic.
|>
|> Yes; so?
|>
|> For a program that contains `long long', after issuing a diagnostic,
|> the compiler is free to choose whatever semantics it likes. However,
|> for a program that does not contain `long long', but does contain a
|> literal that will fit in `unsigned long' but not in `long', e.g.
|> 2147483648, the DWP specifies the semantics, and a conforming compiler
|> is _not_ free to make the type of such literals `long long'.
Correct. Presumably, to be useful, such a compiler will have two modes,
one which accepts long long, and handles type promotion correctly for
that case, and another which doesn't, and handles type promotion
correctly for C++. While I would consider it a very bad choice, I
suppose that a compiler could select the "long long" accepting mode
automatically (after issuing a diagnostic) if the program contained
"long long", and the normal most otherwise.
I believe that g++'s policy is to have the extensions active by default;
you need special options (-ansi -pedantic) for g++ to be a C++ compiler
(as opposed to a compiler for G++, a language which is confusingly
similar to C++, but not identical). Obviously, it is up to the authors
of G++ (the language) to decide what rules they want to use for type
promotion; since they are, in fact, defining a new language, anything
goes.
Just as obviously, if I use "long long", I WON'T compile my program with
a C++ compiler; I WILL use whatever options are necessary to get the
extension. And I won't expect the C++ type promotion rules to be
applicable as such, since I am working in a different system of types.
(Because the language is so similar to C++, I would expect the type
promotion rules to conform to the *spirit* of C++. But conforming to
the spirit of C++ would require 2147483648 to have type "long long".)
|> >I think that the extension is worthwhile. (Actually, I think it's a
|> >hack, but for the point of argument...) But if you are adding integral
|> >types, which can be used in constant integral expressions, you have to
|> >redefine the promotion rules in some way anyway. What do you do if the
|> >literal it too large to fit in an unsigned long?
|>
|> Well, in that case the DWP says the program is ill-formed, so the compiler
|> must issue a diagnostic; but after that it has issued the diagnostic,
|> it can freely give the literal type `long long' and keep going.
Correct. And it can freely handle type promotion in a way natural to
the extention it has invoked.
(Again, however, I think that g++ is doing its users a disservice in
making such extensions the default mode. The only people who don't read
compiler documentation, and just use the default mode, are beginning
students, who also suppose that anything the compiler accepts is
"standard" C++. As one of the moderators of comp.lang.c++.moderated,
we've been insulted several times by posters for refusing postings
concerning such "standard" C++ features as "__cdecl" or "__far". If
Linux ever replaces the MS-Windows as the standard newbe platform, I
fear that we will get similar insults concerning nested functions et
at.)
|> >In practice, such extensions should only be active if you have given a
|> >specific option requesting them. If I request a long long type, I
|> >certainly expect it to fit coherently into the type system, and give the
|> >expected results.
|>
|> Do you expect this even if doing so would violate standards conformance
|> for the subset which does _not_ use `long long'?
If I don't use "long long", I won't use the option which turns it on.
Either I'm compiling C++, or I'm compiling a similar (but not identical)
language.
|> That might causes _other_ parts of your program, e.g. the header files
|> in some third-party library that you are using, to break, if they
|> relied on behaviour specified by the ANSI C standard and the C++ DWP.
|>
|> In that case, it wouldn't be a true extension, because you would be
|> changing the semantics of the base language.
OK. I can buy this. Two points, however:
1. Are you saying that C++ should adapt rules to facilitate such
extensions?
2. I think that there is always some risk of breaking third-party
headers, etc. when using extensions. In this case, I consider the risk
negligible; the number of cases where the difference is perceptible are
extremely limited, and mostly occur in code (not in headers), and,
generally, such third party software is targetting multiple platforms,
and cannot make accurate assumtions concerning the type of the constant
anyway. (The second point may reflect some idealism on my part: third
party software vendors should write high quality portable code.)
|> >|> >This is all a quality of implementation issue however. The standard
|> >|> >says nothing about long long.
|> >|>
|> >|> Yes, but it does place restrictions on what constitutes a conforming
|> >|> extension, which constrain how a conforming implementation can implement
|> >|> `long long'.
|> >
|> >Yes. It says explicitly that a conforming implementation cannot
|> >implement long long.
|>
|> No, it does not. A conforming implementation certainly can implement
|> `long long'. For example, `gcc -ansi -pedantic' is (modulo bugs) a
|> conforming implementation, and it implements `long long'.
|>
|> What the C standard (and similarly the C++ DWP) says implies that a
|> conforming implementation can implement `long long', but just not with the
|> rules for types of integral literals that you would like.
In fact, just not with reasonable rules for type promotion.
What's wrong with just saying: if you want "long long", you don't want
C++? (You may want something very similar, like G++.) And what's wrong
with being required to know what language you are compiling in?
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: willhall@idt.net (Will Hall)
Date: 1997/03/27 Raw View
In article <rf5hghzvxhc.fsf@vx.cit.alcatel.fr>, James Kanze
<james-albert.kanze@vx.cit.alcatel.fr> wrote:
> |> (1) Require, for all integer literals x>=0 such that the mathematical
> |> value -x is representable in a given signed type, that x also be
> |> representable in that type. (This amounts to, essentially, changing the
> |> range of int and long on 32-bit implementations to be (-2^31 + 1, 2^31 -
> |> 1). )
>
> This doesn't even require a change in the standard;
Explicitly labeling behavior for a number -x as implementation-defined, if
x is non-representable, would constitute a change to the latest draft.
> such an
> implementation is legal now (I'm fairly certain). In fact, I've
> actually used an implementation that did this: 2's complement, but
> defined INT_MIN to be -INT_MAX.
>
> In practice, it doesn't work out too well. I've long forgotten the
> exact problems, and maybe I wouldn't even feel them as problems today.
Too bad -- it would be interesting to hear them.
> I suspect that there are too many other things
> that will break if int's really can take on values not in the range of
> INT_MIN...INT_MAX. Formally, I suspect that they are broken already, in
> the sense that the standard does allow this (and programs which happen
> to use such values invoke undefined behavior), but in practice, they
> work under all current implementations, and *requiring* an
> implementation to break them is probably asking too much.
Having the standard require representability of -x for all representable x
is not the same as requiring an implementation to break for -x s.t. x is
not representable. On the contrary, for implementations on which -2^31
e.g. is already usable -- if not directly specifiable (I'm sure you'd
agree there are many) -- there would be no noticeable effect.
The effect would be that all signed integer literals _required_ by the
standard would now be directly specifiable (i.e., the direct intuitive
specification would yield the intuitively expected value of the
intuitively expected type).
Just as you, M. Kanze, have stated that you don't mind that `int i =
-2147483648;' has an implementation-defined value, because you trust that
all "real life" implementations will do the right thing, should you not
(by that logic) agree that, if the same expression _still_ works with the
above change to the standard (one which makes the standard more
self-consistent and less counter-intuitive and, after all, only affects
this one particular seldom-used number, as you seem to view it) --
shouldn't your attitude to such a change be indifferent to favorable?
-Will Hall
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: James Kuyper <kuyper@wizard.net>
Date: 1997/03/27 Raw View
James Kanze wrote:
>
> willhall@idt.net (Will Hall) writes:
...
> |> "non-portable". To repeat, this interpretation of "portable" is absurdly
> |> restrictive and precludes sensible discussion of portability between
> |> conforming 32-bit implementations and conforming 64-bit implementations.
>
> The question is: are we talking about the standard, or not? A program
> which uses int's to store values like 100000 is not portable, and the
> standard doesn't guarantee it will work. In fact, I've used a number of
> implementations where it won't work.
Doesn't the standard guarantee that such a program will work on any
implementation where INT_MAX>=100000 ? I've been assuming that it did; I
assumed that this was part of what INT_MAX means. I thought that I could
store any value in the range INT_MIN <= n <= INT_MAX in an integer,
without giving the implementation an excuse for unexpected behavior.
Similarly, until this thread started, I thought that the standard
guaranteed that I could express any value between LONG_MIN and ULONG_MAX
as an integral type literal, even if that literal was not expressable
under all conforming implementations. I understand now that this is not
true, but I don't like it.
Is the following an accurate statement of your point of view?
"If a program is not portable to every conforming implementation, the
standard (does not ? should not ? can not) make any guarantees about its
behavior under any implementation".
If this is not what you believe, can you provide a similarly worded
statement that does justify your statements?
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/28 Raw View
Christopher Eltschka <celtschk@physik.tu-muenchen.de> writes:
|> James Kanze wrote:
|>
|> [...]
|>
|> > |> So, we have an example of a (familiar) class of implementations (namely,
|> > |> those with 32-bit int and 32-bit long) that have a representation for
|> > |> -2147483648 but that do _not_ allow for this value's direct specification.
|> >
|> > Except that they do allow it.
|> >
|> > If my statement is wrong, it is remarkably easy to disprove: just show
|> > an implementation where it doesn't work.
|> >
|> > I know that this has nothing to do with the standard, but if you use
|> > such a value, you are outside of the guarantees of the standard anyway.
|>
|> There can still be problems with this value:
|> try f.ex. with gcc under Linux
|>
|> int i=-2147483648;
|> assert(i<0); /* works */
|>
|> long long l=-2147483648;
|> assert(l<0); /* fails */
There is no "long long" type in C++, so this is a compiler extension.
IMHO, if a compiler offers such an extension, it should also extend
preprocessor arithmetic to cover the case. It would also seem natural
that the implicit promotions take this into account, so that 2147483648
would have type "long long", and the above would work.
This is all a quality of implementation issue however. The standard
says nothing about long long.
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/28 Raw View
willhall@idt.net (Will Hall) writes:
|> In article <rf5g1xjvwja.fsf@vx.cit.alcatel.fr>, James Kanze
|> <james-albert.kanze@vx.cit.alcatel.fr> wrote:
|>
|> > I've addressed the two proposals in another posting, so I won't talk
|> > about them here. If you think that the problem is real, and serious,
|> > make a concrete proposal; if there are no other problems with it, I
|> > won't oppose it. (Note that I consider the fact that an int may have a
|> > value not in the range INT_MIN...INT_MAX unacceptable.
|>
|> Care to elaborate? I assume you are referring to my suggestion that, in
|> effect, INT_MAX == INT_MIN be a property of implementations, and that if
|> an implementation chooses to allow ints which are < INT_MIN, e.g., then it
|> is operating in implementation-defined territory. Why is that
|> unacceptable, exactly?
The problem is that I don't remember what the problems were. I used
such an implementation once, and I didn't like it at all, but I cannot
remember exactly why.
I can think of vague reasons involving program verification (if x is
declared an int, it is by definition proved that it has a value in the
range INT_MIN...INT_MAX). In fact, I'm sure that this was not the point
then. Also, given that overflow is undefined behavior today, anyone
doing program verification will be asserting that there results outside
of the range INT_MIN...INT_MAX are not possible anyway.
This is an easy suggestion to test. Just modify the value of INT_MIN,
etc. in your headers, grab big chunks of existing code, and go to it.
You should soon get a feel of whether there are any real problems or
not.
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/28 Raw View
willhall@idt.net (Will Hall) writes:
|> Well then, how about changing the standard to eliminate the "aesthetic"
|> problem as you call it without generating any new work for lexer writers?
|> If you're not sure what I mean by this, please see my recent posts on the
|> matter (I wouldn't want to repeat myself ;-).
Having thought about the problem a little bit more...
I think that there could be a solution: it would represent a radical
change in the way C/C++ has been described until now, but I don't think
it would have much significant practical change (except to break
programs which count on -2^31 being positive:-).)
My idea would be that integer literals be untyped (but signed), and that
the implementation be required to do integral constant arithmetic in
"infinite" precision. (In practice, there must be implementation
limits, but they should be required to be at least twice the number of
bits in the largest integral type? or all values in the range
LONG_MIN...ULONG_MAX?) Only when the integral literal is used does it
aquire a type, according to its value and the context.
This is trickier than it looks: there are several implications to be
considered:
1. Function overloading. I don't think that there are any real problems
here; the current rules are rather confusing anyway (the actual function
depends on the value, and may change from one implementation to the
next).
2. The use of the U and L suffixes. This is somewhat more difficult; if
we don't want to break existing code, the presence of a suffix in the
constant expression must constrain the type of the expression.
There are probably other points I haven't thought of.
It is too late in the C++ standardization to consider this. I think it
is more a C issue anyway; I wouldn't want C and C++ to differ on this.
So if anyone is interested, they should probably make the proposal to
the C standards committee, not to the C++ one. (I'm not sure, but it
may also be too late for this round of C, as well.)
Anyway: I like the idea. I think that it could be made to work. I also
think that the current situation is not a real problem, and that there
are more important things to worry about, so I'm not ready to invest any
real effort in getting the idea adopted.
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/03/29 Raw View
James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:
>Christopher Eltschka <celtschk@physik.tu-muenchen.de> writes:
>
>|> There can still be problems with this value:
>|> try f.ex. with gcc under Linux
>|>
>|> int i=-2147483648;
>|> assert(i<0); /* works */
>|>
>|> long long l=-2147483648;
>|> assert(l<0); /* fails */
>
>There is no "long long" type in C++, so this is a compiler extension.
>IMHO, if a compiler offers such an extension, it should also extend
>preprocessor arithmetic to cover the case. It would also seem natural
>that the implicit promotions take this into account, so that 2147483648
>would have type "long long", and the above would work.
But if a compiler did that, then it would no longer be conforming.
The standard specifies that integer literals that can fit into an unsigned
long but not a long should have type unsigned long. An extension
which gave such a value the type "long long" would not be a conforming
extension. I don't see how "implicit promotions" could fix this.
>This is all a quality of implementation issue however. The standard
>says nothing about long long.
Yes, but it does place restrictions on what constitutes a conforming
extension, which constrain how a conforming implementation can implement
`long long'.
Hopefully C9X will change the rules when it adds `long long', so that
the code fragment above will work in conforming C9X implementations
(even though doing so would technically not be backwards compatible
with C89).
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Oleg Zabluda <zabluda@math.psu.edu>
Date: 1997/03/20 Raw View
James Kanze <james-albert.kanze@vx.cit.alcatel.fr> wrote:
: If INT_MIN (or LONG_MIN) == -2147483647, ...
Small comment:
INT_MIN is an obsolete way to do that. The modern way is:
#include <limits>
numeric_limits<int>::min();
Oleg.
--
Life is a sexually transmitted, 100% lethal disease.
==> http://www.math.psu.edu/zabluda/sheep.html before e-mailing about cloning.
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: James Kuyper <kuyper@wizard.net>
Date: 1997/03/21 Raw View
Will Hall wrote:
>
> In article <rf5k9n4fdez.fsf@vx.cit.alcatel.fr>, James Kanze
> <james-albert.kanze@vx.cit.alcatel.fr> wrote:
...
[re: -2^31 ]
> > ... in real life, the number is portable to all machines on which
> > it is representable.
>
> If you are referring to the number -2^31, you are mistaken.
...
Can you please provide a specific counter-example? There is a loophole
in the standard, and Mr. Kanze does not seem to disagree with you about
that. He is merely claiming that no one has yet produced an
implementation that slips through this particular loophole.
I don't think Mr. Kanze is mistaken, I just don't care about the truth
of his statement. If -2^31 can be represented in a given implementation,
the standard itself should guarantee that I can express it as
-2147483648; I shouldn't have to rely upon the historical accident that
no one has implemented this poorly yet.
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/03/21 Raw View
Oleg Zabluda <zabluda@math.psu.edu> writes:
>James Kanze <james-albert.kanze@vx.cit.alcatel.fr> wrote:
>: If INT_MIN (or LONG_MIN) == -2147483647, ...
>
>Small comment:
>
>INT_MIN is an obsolete way to do that. The modern way is:
>#include <limits>
>numeric_limits<int>::min();
Well, since this is comp._std_.c++, I should point out that that ought
to be
#include <limits>
std::numeric_limits<int>::min();
^^^^^
Of course, this will work only if your compiler supports namespaces.
`INT_MIN' is going to be more portable for quite some time.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: willhall@idt.net (Will Hall)
Date: 1997/03/21 Raw View
In article <01bc3602$4cc5d7c0$1371adce@azguard>, "Bradd W. Szonye"
<bradds@concentric.net> wrote:
> Most implementations I have seen actually define INT_MIN as (-X-1) where X
> depends on the size of the type. Note that a vendor who called -2147483648
> a signed integer (given the ongoing assumptions in this thread--32bit 2'sc.
> int and long) would in fact be implementing it poorly. 2147483648 is an
> unsigned long integer according to 2.13.1,
> so -2147483648 is a signed long integer with implementation-defined value.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This is false. If you review the language of the draft standard more
carefully, I believe you will find it to be the case that (as has been
spelled out several times so far in this thread):
(1) the literal 2147483648 (synonymous herein with 2^31), too large to be
an int, is taken (2.13.1[2]) as an unsigned long int.
(2) since the literal quantity achieved in (1) is unsigned, unary `-'
(5.3[7]) subtracts it from 2^n (where n == the # of bits in the type of the
operand [unsigned long int] == 32), yielding 2^32 - 2^31 = 2^31 with
type unsigned long int (still from 5.3[7]). (Thus the net effect of the
unary negation is nil.)
In summary, -2147483648 is an unsigned long integer with whose value is
mandated by the standard for the subset of implementations under
discussion.
> Fortunately, the problem only affects source-code generators and (arguably
> poor) programmers who put such magic numbers in code. The former can check
> for the special case (abs(x) > INT MAX), and the latter, er, sort of
> deserve what they get.
This is to sidestep arguments I, for one, have made for the desirability
of direct specifiability of all representable numbers, and to implictly
devalue them without addressing them or responding directly. In fact, the
"deserve what they get" assertion is a classic example of unsound logic in
action and has little or nothing to do with the standard and the question
of whether it should allow for a more direct specification of all
representable values of type int than it does at present.
BTW, would anyone care to provide me with a decent definition of "magic
number"? I can't find the term in the draft standard, but it seems to be
coming up with increasing frequency in this thread. FWIW, here is my guess
at its definition based on the context of the aforementioned usage
examples:
DEFINITION: By a "magic number" we shall mean (for a given implementation
of the C++ standard) any representable value of an integer or floating
type which, however, due to oversight, puzzlement or deep wisdom on the
part of standard-writers to date, is not directly specifiable by the
language. (By directly, we mean using one or fewer unary operators.)
Further, any users of the language who should so much as _wish_ to specify
such numbers directly, let alone _act_ on that wish, shall be deemed to
deserve what they get. ;-)
-Will Hall
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: willhall@idt.net (Will Hall)
Date: 1997/03/21 Raw View
In article <3331AE0C.41C6@wizard.net>, James Kuyper <kuyper@wizard.net> wrote:
> Will Hall wrote:
> >
> > In article <rf5k9n4fdez.fsf@vx.cit.alcatel.fr>, James Kanze
> > <james-albert.kanze@vx.cit.alcatel.fr> wrote:
> ...
> [re: -2^31 ]
> > > ... in real life, the number is portable to all machines on which
> > > it is representable.
> >
> > If you are referring to the number -2^31, you are mistaken.
> ...
> Can you please provide a specific counter-example? There is a loophole
> in the standard, and Mr. Kanze does not seem to disagree with you about
> that.
Unless I misunderstood Mr. Kanze (not at all outside the realm of
possibility), he would not agree that there is a loophole in the standard.
In fact, here's a quote from one of his recent posts:
>: The "loophole" which
>: triggers "implementation-defined" is the presence of the value, not the
>: way it is written.
> He is merely claiming that no one has yet produced an
> implementation that slips through this particular loophole.
Though it would be trivial to create such a conforming implementation, I
see the (rather small) distinction you are making and concede that my "you
are mistaken" reply might, rigorously, have been too hasty without our
(Mr. Kanze and I) having first agreed on a definition of "in real life".
However, I don't have the energy at present to explore the fascinating
minutiae that no doubt lie along the path down which that would lead us.
Instead, I'll simply agree with your next statement, prefaced by the two
words "Rigorously speaking":
> I don't think Mr. Kanze is mistaken, I just don't care about the truth
> of his statement. If -2^31 can be represented in a given implementation,
> the standard itself should guarantee that I can express it as
> -2147483648; I shouldn't have to rely upon the historical accident that
> no one has implemented this poorly yet.
In addition, I would like to put forward an informal suggestion which,
though possibly not the best solution, might at least make the standard
more honest about what the language can handle (without, e.g., resorting
to indirect specification of representable integer values) without
requiring additional work for the lexer-writers of the world:
Require that, for signed integer types, for any non-negative value x such
that -x is representable, the value x must also be representable. In
particular, this could be interpreted for two's complement implementations
as meaning that int and long will range from -2^n + 1 to 2^n - 1 (where n
is 32, 64, etc. depending in practice upon the hardware architecture).
If, as a non-standard extension, an implementation so elected, it would be
free to allow signed integer types to assume the value -2^n (which it
would be free to deal with as it saw fit -- or perhaps even in a somewhat
restricted way indicated by the standard).
Will Hall
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: hpa@transmeta.com (H. Peter Anvin)
Date: 1997/03/23 Raw View
Followup to: <199703211647.LAA22507@u1.farm.idt.net>
By author: willhall@idt.net (Will Hall)
In newsgroup: comp.std.c++
>=20
> In addition, I would like to put forward an informal suggestion which,
> though possibly not the best solution, might at least make the standard
> more honest about what the language can handle (without, e.g., resortin=
g
> to indirect specification of representable integer values) without
> requiring additional work for the lexer-writers of the world:
>=20
> Require that, for signed integer types, for any non-negative value x su=
ch
> that -x is representable, the value x must also be representable. In
> particular, this could be interpreted for two's complement implementati=
ons
> as meaning that int and long will range from -2^n + 1 to 2^n - 1 (where=
n
> is 32, 64, etc. depending in practice upon the hardware architecture).
>=20
This is no better than what we have now. I would like to propose the
following alternative:
Require that, for any signed integral type, if -x is representable, a
literal constant of value x must be properly handled by the compiler
*if and only if* it is preceded by a unary minus sign, so that the
value of the resulting constant expression is -x. This works
correctly automatically on two's-complement, one's-complement,
sign-magnitude, BCD and balanced ternary machines (in the latter four
cases since -INT_MIN =3D=3D INT_MAX, in the former case due to the nature
of the rollover[1].) For machines with truly *weird* handling of
negative numbers[2] it may require the compiler to keep additional
precision during the translation stages, but it would affect such a
vanishingly small number of machines -- and those that it would affect
would probably have really bizarre compilers anyway -- that I don't
think that is an onerous requirement.
-hpa
[1] As previously discussed in this thread: -(-INT_MIN) =3D=3D -INT_MIN =3D=
=3D
INT_MIN on a 2's complement machine.
[2] If someone can find a real-life example where the compiler would
have to do something special if this was implemented, I would
really like to hear about it, just for kicks...
--=20
Always looking for a few good BOsFH. ** Linux - the OS of global cooper=
ation
I am Bah=E1'=ED -- ask me about it or see http://www.bahai.org/
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/24 Raw View
willhall@idt.net (Will Hall) writes:
|> I will rephrase your statements to preserve meaning but elucidate the
|> contradiction:
|>
|> Stmt 1: For that subset of all conforming implementations on which
|> -2147483648 can be represented as a value of type int, it can be specified
|> as `-2147483648'.
|> Stmt 2: The C++ statement `int i = -2147483648;' has results on typical
|> 2's complement 32 bit machines which are not guaranteed by the standard.
|>
|> Stmt 1 contradicts stmt 2, principally because stmt 1 is false. Stmt 2 is
|> true according to reasonable interpretations of the word `typical'.
If I may say so, I think that the fundamental difference of our opinions
is elsewhere. Basically, we agree that statement 2 is true, because it
makes a statement about *all* conforming implementations, including
those which don't exist, but conceivably could. (I don't know if there
actually exists a 32 bit 1's complement implementation, but it would be
legal under the standard if it did exist.)
I think the problem we are having is with the definition of "that subset
of conforming implementations" in statement 1. My argument is that in
taking the subset, you are taking a subset; you are *not* concerned with
all possible implementations, but only those meeting certain criteria.
Furthermore, I content that such an action takes you out of the
standard, so talking about implementations which might conceivably exist
is no longer relevant. The question is only *interesting* if it applies
to real implementations. (I have no problem conceiving of an
implementation on which -2147483648 is representable, but which will not
accept it written in this fashion. I also have no problem conceiving of
an implementation which inserts a five hour empty loop into the
generated code for each C++ statement. I consider that the two
implementations are about equally likely, and it doesn't particularly
bother me that the standard doesn't forbid either.)
In practice, I think it is far more likely to run across an
implementation which doesn't support the value -2147483648 at all; 1's
complement machines do exist, although they are rare. So I won't use
the value at all if I can avoid it. If I do use it, then I am knowing
targetting a subset of real implementations, not all conceivably
possible implementations. In which case, the only real question is "is
there a real implementation on which -2147483648 is representable, but
where I cannot write it this way?"
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/24 Raw View
James Kuyper <kuyper@wizard.net> writes:
|> Will Hall wrote:
|> >
|> > In article <rf5k9n4fdez.fsf@vx.cit.alcatel.fr>, James Kanze
|> > <james-albert.kanze@vx.cit.alcatel.fr> wrote:
|> ...
|> [re: -2^31 ]
|> > > ... in real life, the number is portable to all machines on which
|> > > it is representable.
|> >
|> > If you are referring to the number -2^31, you are mistaken.
|> ...
|> Can you please provide a specific counter-example? There is a loophole
|> in the standard, and Mr. Kanze does not seem to disagree with you about
|> that. He is merely claiming that no one has yet produced an
|> implementation that slips through this particular loophole.
|>
|> I don't think Mr. Kanze is mistaken, I just don't care about the truth
|> of his statement. If -2^31 can be represented in a given implementation,
|> the standard itself should guarantee that I can express it as
|> -2147483648; I shouldn't have to rely upon the historical accident that
|> no one has implemented this poorly yet.
So we must agree to disagree...
I don't think that it is a "historical accident" that no implementation
has failed this yet; I think that there are strong, concrete reasons
which motivate an implementation to make this work. They are couched in
terms like "market share", rather than "standards conformance". (From a
practical point of view, such motivations are probably more efficient
than the "standards conformance" ones.)
In all fairness to Will Hall, I don't think I expressed myself clearly
in my earlier postings, with statements to the effect of "it will
work". Considering that this is a forum for discussions of the
standard, it is understandable that this would be interpreted as "the
standard guarantees that it will work". I should have made it clearer
that IMHO, if I limit the discussion to a subset of conforming
implementations, I might as well limit it to a subset the behaves the
way I want, unless there really are (or might conceivably be)
implementations that don't behave as I expect.
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/24 Raw View
James Kuyper <kuyper@wizard.net> writes:
|> James Kanze wrote:
|> ...
|> > |> [ of `int i = -2147483648;' ]
|> ...
|> > What is getting boring is that I am repeating myself. Apparently, I
|> > wasn't clear. If you stick rigorously within the standard, there is no
|> > problem, since the value cannot occur. If you are practically concerned
|> > with portability, there is no problem, since the obvious expression
|> > works in all cases where the value is representable.
|>
|> The standard could guarantee that such expressions work in all cases
|> where their value is representable, while leaving the result undefined
|> in other cases.
The problem is that the value of the expression -2147483648 is not
representable in a 32 bit signed int, since the value is the positive
number 2147483648. It would take some extremely tricky special case
wording to make it work.
Several people have pointed out to me in private email (and no doubt
others in postings I've not seen yet) that while -2147483648 will almost
certainly work in the above case, the expression does not have the type
(int or long) that one would intuitively expect; on an implementation
with 32 bit longs, it will have an unsigned type. This will, in turn,
result in unexpected behavior with regards to function overloading and
comparisons.
I recognize that this could be a problem in certain cases. Since,
however, this value cannot be used in portable code anyway, and making
it work in the above cases would require some really tricky special
cases, probably resulting in counter-intuitive behavior elsewhere, I
would still oppose any changes in this in the standard.
(I think in fact that there is one good solution: require the compiler
to work in infinite signed integral arithmetic, and to complain if the
results are too big for the final context. If I were designing a new
language, I think I would try for something like this, but there are a
number of reasons why it cannot be retrofitted to C or C++.)
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/24 Raw View
willhall@idt.net (Will Hall) writes:
[Concerning -2^31...]
|> > And the problem I see with your argument is that the standard doesn't
|> > even guarantee that the value exists. If we are arguing about the
|> > standard,
|>
|> We are.
|>
|> > ... and 100% portable code,
|>
|> We are not -- as you interpret it, that would be a foolish thing to argue
|> about (esp. in the context of negative integer literals), as it would
|> exclude discussion of many interesting & important issues that arise only
|> for a proper subset (however practically relevant) of all possible
|> implementations. The practically relevant subset about which _I_ have been
|> arguing in recent posts is that set of conforming implementations which
|> have the following properties: representable int and long range from -2^31
|> to 2^31 - 1, and representable unsigned long ranges from 0 to 2^32 - 1.
|> Let us call this "The two's-complement-like 32-bit subset", or "The tcl32
|> subset".
[...]
|> > I agree that the implementations which will not support the value
|> > -2147483648 are rare, rare enough that if the implementation needs the
|> > value, it might be an acceptable compromise to forgo portability to
|> > these implementations. Would you not admit, however, that exactly the
|> > same argument holds for writing the literal -2147483648, and not using
|> > some other fancy work-around.
|>
|> Sorry, you lost me there ... I don't follow your argument, so I can't
|> admit anything based upon it just yet.
My point is simple: we are discussing a subset of the implementations.
(We agree there.) As far as I can tell, writing the literal -2147483648
works (at least in the case of initializing an int) on all machines in
this subset. It's not guaranteed to work by the standard, but this is a
foregone conclusion; if it were guaranteed, we wouldn't be talking about
a subset.
I repeat: if you are writing 100% portable code, you cannot use the
value, period. If you are only concerned with a subset of conforming
implementations, then show me an implementation which is in your target
subset where writing -2147483648 doesn't work.
|> > To correct the misinformation in the above excerpt: the value
|> > -2^32 cannot appear in a portable program. Period.
|> ^^^^^
|> [ Presumably, you mean -2^31, as the appearance of -2^32 was not being
|> adressed in that post ... while your assertion holds for -2^32 in the
|> context of this discussion (tcl32 subset), it does _not_ hold for -2^31. ]
|>
|> Not according to the absurdly restrictive interpretation of "portable"
|> which you seem to be employing. If we were to make the friendly agreement
|> that, in the context of discussion of the specifiability of -2^31 as
|> -2147483648 versus -2147483647 - 1, assertions regarding portability and
|> anything else shall (unless it is explicitly indicated otherwise) be taken
|> to refer to the contextually relevant subset of all conforming
|> implementations tcl32 detailed above, then these several consequences
|> would follow from the draft standard:
Exactly my point: show me a conforming tcl32 implementation where
writing -2147483648 doesn't work.
|> (1) the value -2^31 is representable.
|> (2) the expression (-2147483647 - 1) is a portable (if indirect) means of
|> specifiying -2^31. The same holds for all expressions (-x - y) where x and
|> y are integer literals (as defined in the draft, i.e., not preceded by a
|> sign) with 0 <= x <= 2^31 - 1 and y equal to (2^31 - x).
|> (3) the character sequence `-2147483648' is comprised of two tokens (the
|> unary negation operator followed by 2147483648), and there does not exist
|> a usage of it which is guaranteed to yield a particular value of type int;
|> in particular, the standard says that the value of each of these
|> expressions is implementation-defined:
|>
|> (a) (int) -2147483648
|> (b) i = -2147483648 /* where i is of type int */
The standard says that whether the value is even representable is
implementation defined. I totally agree that it is reasonable, in the
real world (although perhaps not in comp.std.c++:-), to limit your
targets to the subset of machines on which -2147483648 is a legal value.
My argument is simply that since you are limiting your targets to the
subset of (possibly) conforming implementations which support this
value, you might as well limit them to the subset which also allows you
to write it this way, given that, as far as I can tell, the two subsets
are identical.
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/24 Raw View
willhall@idt.net (Will Hall) writes:
|> In article <01bc3602$4cc5d7c0$1371adce@azguard>, "Bradd W. Szonye"
|> <bradds@concentric.net> wrote:
|>
|> > Most implementations I have seen actually define INT_MIN as (-X-1) where X
|> > depends on the size of the type. Note that a vendor who called -2147483648
|> > a signed integer (given the ongoing assumptions in this thread--32bit 2'sc.
|> > int and long) would in fact be implementing it poorly. 2147483648 is an
|> > unsigned long integer according to 2.13.1,
|> > so -2147483648 is a signed long integer with implementation-defined value.
|> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|>
|> This is false. If you review the language of the draft standard more
|> carefully, I believe you will find it to be the case that (as has been
|> spelled out several times so far in this thread):
|>
|> (1) the literal 2147483648 (synonymous herein with 2^31), too large to be
|> an int, is taken (2.13.1[2]) as an unsigned long int.
|>
|> (2) since the literal quantity achieved in (1) is unsigned, unary `-'
|> (5.3[7]) subtracts it from 2^n (where n == the # of bits in the type of the
|> operand [unsigned long int] == 32), yielding 2^32 - 2^31 = 2^31 with
|> type unsigned long int (still from 5.3[7]). (Thus the net effect of the
|> unary negation is nil.)
|>
|> In summary, -2147483648 is an unsigned long integer with whose value is
|> mandated by the standard for the subset of implementations under
|> discussion.
Just to pick nits, but -2147483648 is either an unsigned long integer,
or a signed long integer, depending on the value of LONG_MAX. In both
cases, however (and thus, for all conforming implementations), the value
is exactly specified by the standard; the implementor has no leaway here
once he has fixed the value of LONG_MAX.
|> > Fortunately, the problem only affects source-code generators and (arguably
|> > poor) programmers who put such magic numbers in code. The former can check
|> > for the special case (abs(x) > INT MAX), and the latter, er, sort of
|> > deserve what they get.
|>
|> This is to sidestep arguments I, for one, have made for the desirability
|> of direct specifiability of all representable numbers, and to implictly
|> devalue them without addressing them or responding directly. In fact, the
|> "deserve what they get" assertion is a classic example of unsound logic in
|> action and has little or nothing to do with the standard and the question
|> of whether it should allow for a more direct specification of all
|> representable values of type int than it does at present.
I've seen strong statements saying that direct specificablility of all
representable numbers is desirable, but I've not seen any arguments as
to why.
The only argument I've seen against the current interpretation of
-2147483648 to date is that it has an unexpected type. I am sensitive
to this argument, but I don't really see any good solution; at least no
one has proposed one.
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: James Kuyper <kuyper@wizard.net>
Date: 1997/03/25 Raw View
Will Hall wrote:
>
> In article <01bc3602$4cc5d7c0$1371adce@azguard>, "Bradd W. Szonye"
...
> > a signed integer (given the ongoing assumptions in this thread--32bit 2'sc.
> > int and long) would in fact be implementing it poorly. 2147483648 is an
> > unsigned long integer according to 2.13.1,
> > so -2147483648 is a signed long integer with implementation-defined value.
...
> In summary, -2147483648 is an unsigned long integer with whose value is
> mandated by the standard for the subset of implementations under
> discussion.
Technically correct, but in most cases where it would be written,
-2147483648 will be immediately cast to a signed integer, which makes
the result implementation defined.
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: willhall@idt.net (Will Hall)
Date: 1997/03/25 Raw View
In article <rf5ohc9odo2.fsf@vx.cit.alcatel.fr>, James Kanze
<james-albert.kanze@vx.cit.alcatel.fr> wrote:
> My point is simple: we are discussing a subset of the implementations.
> (We agree there.) As far as I can tell, writing the literal -2147483648
> works (at least in the case of initializing an int) on all machines in
> this subset.
The subset consists of conforming implementations, not of "machines". It
is entirely possible to create an implementation which conforms to the
current draft standard but on which the expression -2147483648 (note that
this is _not_ a literal) does not "work". MY MAIN POINT: I would prefer
the standard to be such that this were not the case.
> It's not guaranteed to work by the standard, but this is a
> foregone conclusion; if it were guaranteed, we wouldn't be talking about
> a subset.
That's faulty logic: the guarantees of the standard can be a function of
certain parameters (p0, p1, ..., pN) which vary from one implementation to
the next (e.g., max & min values of builtin types). The standard can be
designed so that portability from a subset of implementations where
(p0..pN) is (v0, ..., vJ, ..., vN) to a subset where vJ --> vJ_prime
(e.g., where 32-bits changes to 64-bits & max & min values of builtin
types change accordingly) is either maximized or minimized. I'm observing
that the current standard does not _guarantee_ portability of the
expression -2147483648 from 32-bit to 64-bit, especially when it is cast
to a signed type (int or long); nor is the standard _transparent_ in this
regard (i.e., it has the laxity, but does not point it out). I suggest
that the standard be honest about this; it could do so by:
(a) explicitly disavowing representability (for x >= 0) of numbers -x for
which x is not representable (e.g., if 2^31 is not a rep'able int, neither
is -2^31); or
(b) requiring that direct expressions such as -2147483648, which
intuitively (i.e., according to the usual syntax of arithmetic) ought to
result in a representable value (for our example, the value -2^31 of type
int), in fact _do_ result in the intuitively expected value and type; this
would _increase_ the _guaranteed_ portability between 32-bit and 64-bit
implementations.
> I repeat: if you are writing 100% portable code,
Nobody is writing 100% portable code in the sense you seem to mean. Nobody
worries that
> you cannot use the
> value, period. If you are only concerned with a subset of conforming
> implementations, then show me an implementation which is in your target
> subset where writing -2147483648 doesn't work.
I don't need to show you such an example; logic alone reveals that the
standard would _embrace_ such an implementation, whether it presently
exists or not. Also, isn't the fact that -2147483648, though intuitively
an int on systems where it is representable, can be (and in practice on
32-bit systems ACTUALLY IS) guaranteed to be otherwise: of type unsigned
long, for example -- isn't this fact by itself enough to call the current
standard into question?
> The standard says that whether the value is even representable is
> implementation defined.
Yes, just as it says that the representability of any value outside it's
minimum reqired range for a given type is implementation-defined: with
such absurdly restrictive tactics of argument, constructive analysis of
the standard is impossible.
> --
> James Kanze
Will Hall
(willhall@idt.net)
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: willhall@idt.net (Will Hall)
Date: 1997/03/25 Raw View
In article <rf5pvwpoeam.fsf@vx.cit.alcatel.fr>, James Kanze
<james-albert.kanze@vx.cit.alcatel.fr> wrote:
> James Kuyper <kuyper@wizard.net> writes:
>
> |> James Kanze wrote:
> |> ...
> |> > |> [ of `int i = -2147483648;' ]
> |> ...
> |> > What is getting boring is that I am repeating myself. Apparently, I
> |> > wasn't clear. If you stick rigorously within the standard, there is no
> |> > problem, since the value cannot occur. If you are practically concerned
> |> > with portability, there is no problem, since the obvious expression
> |> > works in all cases where the value is representable.
> |>
> |> The standard could guarantee that such expressions work in all cases
> |> where their value is representable, while leaving the result undefined
> |> in other cases.
>
> The problem is that the value of the expression -2147483648 is not
> representable in a 32 bit signed int, since the value is the positive
> number 2147483648. It would take some extremely tricky special case
> wording to make it work.
>
> Several people have pointed out to me in private email (and no doubt
> others in postings I've not seen yet) that while -2147483648 will almost
> certainly work in the above case, the expression does not have the type
> (int or long) that one would intuitively expect; on an implementation
> with 32 bit longs, it will have an unsigned type. This will, in turn,
> result in unexpected behavior with regards to function overloading and
> comparisons.
>
> I recognize that this could be a problem in certain cases. Since,
> however, this value cannot be used in portable code anyway, ...
This has been your assertion all along, and it is still, IMHO, based upon
an absurdly restrictive implicit interpretation of "portable". For a given
builtin type, _no_ value which is outside the minimum range mandated by
the standard is "portable" according to said interpretation. Any program
which relies upon such "non-portable" values is itself non-portable and
therefore not worthy of discussion, according to this reading of the term
"portable". In fact, if one sticks to the above logic, any discussion of,
e.g., 64-bit implementations is not constrained in the least by the
standard, as programs which use such implementations to the utmost are
"non-portable". To repeat, this interpretation of "portable" is absurdly
restrictive and precludes sensible discussion of portability between
conforming 32-bit implementations and conforming 64-bit implementations.
-Will Hall
(willhall@idt.net)
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: willhall@idt.net (Will Hall)
Date: 1997/03/25 Raw View
In article <rf5k9mxobn9.fsf@vx.cit.alcatel.fr>, James Kanze
<james-albert.kanze@vx.cit.alcatel.fr> wrote:
> I've seen strong statements saying that direct specificablility of all
> representable numbers is desirable, but I've not seen any arguments as
> to why.
Here's one argument: On implementations where -2^31 to (2^31 - 1) is the
range of representable int and long, and 0 to (2^32 - 1) is the range of
representable unsigned int and unsigned long, the expression `(int)
-2147483648' (where the cast to int could be explicit or a result of a
standard conversion) has a value which is not mandated by the standard.
(Why do I get the feeling I'm repeating responses I've given before to
James Kanze's repeated questions and assertions? Smell that bandwidth
burning ...)
> The only argument I've seen against the current interpretation of
> -2147483648 to date is that it has an unexpected type.
And that's another one. Now you've seen two "arguments as to why".
> I am sensitive
> to this argument, but I don't really see any good solution; at least no
> one has proposed one.
Two solutions have been proposed (though you may not consider either one
to be good). As I recall, they were (in essence):
(1) Require, for all integer literals x>=0 such that the mathematical
value -x is representable in a given signed type, that x also be
representable in that type. (This amounts to, essentially, changing the
range of int and long on 32-bit implementations to be (-2^31 + 1, 2^31 -
1). )
(2) Require, for all integer literals x>=0 such that the mathematical
value -x is representable in a given signed type, that the direct
expression `-x' shall either:
[a] result in a value of the given type, or
[b] result in a value of a type whose range is not greater in either
direction than that of the given type. (In particular, something which
looks like a direct specification of a representable int shall not end up
having a value of type unsigned long or unsigned int.)
OK, I've rephrased the second one enough that I'd better quote the
original by H. Peter Anvin:
>:Require that, for any signed integral type, if -x is representable, a
>:literal constant of value x must be properly handled by the compiler
>:*if and only if* it is preceded by a unary minus sign, so that the
>:value of the resulting constant expression is -x.
By "properly", I take M. Anvin to have meant: "things that look like
direct specifications of representable negative integers will _not_ result
in unsigned longs or unsigned ints, and will have the value one would
expect intuitively, i.e., mathematically".
-Will Hall
(willhall@idt.net)
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1997/03/25 Raw View
James Kanze wrote:
[...]
> |> So, we have an example of a (familiar) class of implementations (namely,
> |> those with 32-bit int and 32-bit long) that have a representation for
> |> -2147483648 but that do _not_ allow for this value's direct specification.
>
> Except that they do allow it.
>
> If my statement is wrong, it is remarkably easy to disprove: just show
> an implementation where it doesn't work.
>
> I know that this has nothing to do with the standard, but if you use
> such a value, you are outside of the guarantees of the standard anyway.
There can still be problems with this value:
try f.ex. with gcc under Linux
int i=-2147483648;
assert(i<0); /* works */
long long l=-2147483648;
assert(l<0); /* fails */
If you always worked with ints (and longs, which have the same size
in Linux gcc), you won't ever have noticed that -2147483648>0, so
you'd never get even the idea that this is your bug. Switching to
-2147483648L doesn't help either (as longs are the same size as ints).
I think it *is* reasonable to say, it is not a direct representation
of the number, as then you'd be able to initialize a long long with it.
[...]
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: willhall@idt.net (Will Hall)
Date: 1997/03/25 Raw View
In article <01bc397d$42c78b00$b26dadce@azguard>, "Bradd W. Szonye"
<bradds@concentric.net> wrote:
> I've said it before, if you need to specify a negative integer whose
> absolute value is greater than INT_MAX, simply #define it somewhere as
> (-MAX_INT-X) where X is usually one. Like Mr. Kanze, I'm tired of hearing
> the same arguments again and again over what is basically a minor aesthetic
> issue.
Actually, the "discussion" between M. Kanze and me has really evolved
(degenerated?) into one centering on the meaning of portability. If I
repeat any of my arguments, it is only in response to repetitions by M.
Kanze of his.
> Fixing the lexer to deal with this properly would be an ugly hack,
Oh -- "ugly"? Well, just so long as it presents _real_ problems like
_ugliness_, as opposed to mere "aesthetic" ones ;-).
[BTW: does anyone out there consider that the need to #define a value of a
builtin integer type (or to express it as -MAX_INT - 1, the choice is
yours) is something of an "ugly hack"?]
> and the
> only purpose it would serve would be to encourage a poor programming style:
> the use of literal magic numbers.
Well then, how about changing the standard to eliminate the "aesthetic"
problem as you call it without generating any new work for lexer writers?
If you're not sure what I mean by this, please see my recent posts on the
matter (I wouldn't want to repeat myself ;-).
> Ranting about -2 billion and change will not sway people.
That has a nice ring to it -- and I do see your point: if only there were
a more aesthetically pleasing magic number about which I could rant ...
;-)
Cheers,
-Will Hall
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: John David Galt <jdg@but-i-dont-like-spam.boxmail.com>
Date: 1997/03/26 Raw View
> There can still be problems with this value:
> try f.ex. with gcc under Linux
> int i=-2147483648;
> assert(i<0); /* works */
> long long l=-2147483648;
> assert(l<0); /* fails */
It seems to me that on a system where an "int" has the range -2147483648 to
+2147483647, the literal 2147483648 is _not_ a constant of type int. It is
either a constant of some type with a larger range, or it is a syntax error.
If it is a long constant, no problem should occur, because the "=" should
cause an implicit cast to the type of the variable. This cast should always
produce the mathematical value -2147483648 if an int can have that value.
If 2147483648 is an unsigned constant -- then there should _still_ not be a
problem, because the "-" should force an implicit cast to a signed type large
enough to hold the value (or if there is no such type, the "-" should produce
an error, preferably at compile time). If unary minus is not defined this way
then _that_ is the problem.
John David Galt
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: willhall@idt.net (Will Hall)
Date: 1997/03/26 Raw View
In article <199703260001.AA10526@foxtrot.rahul.net>, John David Galt
<jdg@but-i-dont-like-spam.boxmail.com> wrote:
> > There can still be problems with this value:
> > try f.ex. with gcc under Linux
>
> > int i=-2147483648;
> > assert(i<0); /* works */
>
> > long long l=-2147483648;
> > assert(l<0); /* fails */
> It seems to me that on a system where an "int" has the range -2147483648 to
> +2147483647, the literal 2147483648 is _not_ a constant of type int. It is
> either a constant of some type with a larger range, or it is a syntax error.
>
> If it is a long constant, no problem should occur, because the "=" should
> cause an implicit cast to the type of the variable.
A quick perusal of the draft standard (or of earlier posts in this thread)
reveals that 2147483648 is taken as an unsigned long, and that the unary
negation operation results in a value of 2^32 - 2147483648 == 2147483648,
_still_ of type unsigned long. So by the time any standard conversion to
the type of the assignment operator's LHS occurs, the value on the right
is an unsigned long that is > 0.
>This cast should always
> produce the mathematical value -2147483648 if an int can have that value.
I agree that it should, but the standard does not currently enforce this.
On many present-day 32-bit two's complement implementations it works this
way as an artifact of the implementation. One "solution" would be to have
the standard mandate that, on implementations where int can't have the
value 2147483648, int is not required to be able to have the value
-2147483648. Implementations would, of course, be free to enable the value
-2147483648 anyway.
> If 2147483648 is an unsigned constant -- then there should _still_ not be a
> problem, because the "-" should force an implicit cast to a signed type large
> enough to hold the value
Well, perhaps it should, but at present it is not required to by the draft
standard. See 5.3[7] in the draft, on unary negation.
> (or if there is no such type, the "-" should produce
> an error, preferably at compile time). If unary minus is not defined this way
> then _that_ is the problem.
An interesting idea. However, it would still not address the fact that the
only standard-guaranteed portable way to specify the number -2^31 on
implementations where int ranges from -2^31 to 2^31 - 1 is to do something
like (-2147483647 - 1).
-Will Hall
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/26 Raw View
willhall@idt.net (Will Hall) writes:
|> In article <rf5ohc9odo2.fsf@vx.cit.alcatel.fr>, James Kanze
|> <james-albert.kanze@vx.cit.alcatel.fr> wrote:
|>
|> > My point is simple: we are discussing a subset of the implementations.
|> > (We agree there.) As far as I can tell, writing the literal -2147483648
|> > works (at least in the case of initializing an int) on all machines in
|> > this subset.
|>
|> The subset consists of conforming implementations, not of "machines". It
|> is entirely possible to create an implementation which conforms to the
|> current draft standard but on which the expression -2147483648 (note that
|> this is _not_ a literal) does not "work". MY MAIN POINT: I would prefer
|> the standard to be such that this were not the case.
It is also entirely possible to create an implementation which conforms
to the current draft standard, but inserts a five minute empty loop into
each C++ statement it translates.
MY MAIN POINT (borrowed from Steve Clamage): the standard cannot
guarantee a usable implementation.
[...]
|> > I repeat: if you are writing 100% portable code,
|>
|> Nobody is writing 100% portable code in the sense you seem to mean.
Of course not. We all count on other guarantees in addition to the
standard. But this is comp.STD.c++:-).
>From a practical point of view, of course:
1. Are, or will there ever be, implementations where writing -2147483648
will give a value other that expected? and
2. Even if there are: is it a real problem? I've never used the value
in any code I've written, and I cannot, off hand, think of a case where
it would be likely or reasonable. I won't deny that such cases exist,
but I would argue that they are rare enough as to not be a problem.
|> Nobody
|> worries that
|>
|> > you cannot use the
|> > value, period. If you are only concerned with a subset of conforming
|> > implementations, then show me an implementation which is in your target
|> > subset where writing -2147483648 doesn't work.
|>
|> I don't need to show you such an example; logic alone reveals that the
|> standard would _embrace_ such an implementation, whether it presently
|> exists or not.
The standard embraces many implementations which are not reasonable, not
usable, or will never exist, see above.
|> Also, isn't the fact that -2147483648, though intuitively
|> an int on systems where it is representable, can be (and in practice on
|> 32-bit systems ACTUALLY IS) guaranteed to be otherwise: of type unsigned
|> long, for example -- isn't this fact by itself enough to call the current
|> standard into question?
I have already admitted that this is a problem. Again, the value is
rare enough, and it is certainly even rarer in the contexts where the
type will make a difference, that I don't consider it a big problem.
All of the suggestions for fixing it I can think of introduce bigger
problems.
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/26 Raw View
willhall@idt.net (Will Hall) writes:
|> In article <rf5k9mxobn9.fsf@vx.cit.alcatel.fr>, James Kanze
|> <james-albert.kanze@vx.cit.alcatel.fr> wrote:
|>
|> > I've seen strong statements saying that direct specificablility of all
|> > representable numbers is desirable, but I've not seen any arguments as
|> > to why.
|>
|> Here's one argument: On implementations where -2^31 to (2^31 - 1) is the
|> range of representable int and long, and 0 to (2^32 - 1) is the range of
|> representable unsigned int and unsigned long, the expression `(int)
|> -2147483648' (where the cast to int could be explicit or a result of a
|> standard conversion) has a value which is not mandated by the standard.
|>
|> (Why do I get the feeling I'm repeating responses I've given before to
|> James Kanze's repeated questions and assertions? Smell that bandwidth
|> burning ...)
Probably because we are repeating ourselves:-).
I suspect that the real difference in our points is that you insist the
standard give you the guarantee (although I think you accept that
whether the value exists is implementation defined), whereas I take the
point of view that, having already ceased to be "fully portable"
according to the standard, I'm willing to accept the fact that market
pressure will ensure my being able to write the value in a natural form.
|> > The only argument I've seen against the current interpretation of
|> > -2147483648 to date is that it has an unexpected type.
|>
|> And that's another one. Now you've seen two "arguments as to why".
|>
|> > I am sensitive
|> > to this argument, but I don't really see any good solution; at least no
|> > one has proposed one.
|>
|> Two solutions have been proposed (though you may not consider either one
|> to be good). As I recall, they were (in essence):
|>
|> (1) Require, for all integer literals x>=0 such that the mathematical
|> value -x is representable in a given signed type, that x also be
|> representable in that type. (This amounts to, essentially, changing the
|> range of int and long on 32-bit implementations to be (-2^31 + 1, 2^31 -
|> 1). )
This doesn't even require a change in the standard; such an
implementation is legal now (I'm fairly certain). In fact, I've
actually used an implementation that did this: 2's complement, but
defined INT_MIN to be -INT_MAX.
In practice, it doesn't work out too well. I've long forgotten the
exact problems, and maybe I wouldn't even feel them as problems today.
(I paid considerably less attention to portability and to quality back
then.) But basically: I suspect that there are too many other things
that will break if int's really can take on values not in the range of
INT_MIN...INT_MAX. Formally, I suspect that they are broken already, in
the sense that the standard does allow this (and programs which happen
to use such values invoke undefined behavior), but in practice, they
work under all current implementations, and *requiring* an
implementation to break them is probably asking too much.
FWIW: the implementation I used which did this corrected the "error" in
the next release. So I would guess that I wasn't the only one who
didn't like it.
|> (2) Require, for all integer literals x>=0 such that the mathematical
|> value -x is representable in a given signed type, that the direct
|> expression `-x' shall either:
|> [a] result in a value of the given type, or
|> [b] result in a value of a type whose range is not greater in either
|> direction than that of the given type. (In particular, something which
|> looks like a direct specification of a representable int shall not end up
|> having a value of type unsigned long or unsigned int.)
|>
|> OK, I've rephrased the second one enough that I'd better quote the
|> original by H. Peter Anvin:
|> >:Require that, for any signed integral type, if -x is representable, a
|> >:literal constant of value x must be properly handled by the compiler
|> >:*if and only if* it is preceded by a unary minus sign, so that the
|> >:value of the resulting constant expression is -x.
|>
|> By "properly", I take M. Anvin to have meant: "things that look like
|> direct specifications of representable negative integers will _not_ result
|> in unsigned longs or unsigned ints, and will have the value one would
|> expect intuitively, i.e., mathematically".
I consider this to be the more interesting of the two proposals. Having
worked on compilers before, I don't like it one little bit from the
implementers viewpoint, but if it is well specified, it is doable.
The problem is the "well specified" bit; I think that we all understand
what is wanted and needed intuitively, but a standard cannot require
that an implementation do what is "intuitively right". And even well
specified, I'm sure you'll admit that it is a bit of a hack.
For starters as to what "well specified" might look like:
Add the following to the end of 5.3.1/7: "If the cast-expression operand
of the unary - operator is in fact a single literal of an unsigned
integral type, whose value is equal to one more than the maximum value
of the corresponding signed type, and the corresponding negative value
is representable in the signed type, then the results of the unary -
will have the signed type and the correct value."
Of course, this really isn't adequate; according to the above,
-2147483648UL would end up with type signed long. (I'd be interested in
seeing a proposal which would handle this correctly and not wreck havoc
with the phases of compilation.)
And do we really want this kind of special case in the standard? IMHO,
the cure is worse than the disease.
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/26 Raw View
willhall@idt.net (Will Hall) writes:
|> > I recognize that this could be a problem in certain cases. Since,
|> > however, this value cannot be used in portable code anyway, ...
|>
|> This has been your assertion all along, and it is still, IMHO, based upon
|> an absurdly restrictive implicit interpretation of "portable". For a given
|> builtin type, _no_ value which is outside the minimum range mandated by
|> the standard is "portable" according to said interpretation. Any program
|> which relies upon such "non-portable" values is itself non-portable and
|> therefore not worthy of discussion, according to this reading of the term
|> "portable". In fact, if one sticks to the above logic, any discussion of,
|> e.g., 64-bit implementations is not constrained in the least by the
|> standard, as programs which use such implementations to the utmost are
|> "non-portable". To repeat, this interpretation of "portable" is absurdly
|> restrictive and precludes sensible discussion of portability between
|> conforming 32-bit implementations and conforming 64-bit implementations.
The question is: are we talking about the standard, or not? A program
which uses int's to store values like 100000 is not portable, and the
standard doesn't guarantee it will work. In fact, I've used a number of
implementations where it won't work.
There is a significant subset of implementations, of course, where it
will work. If I choose to restrict portability to this subset (a
reasonable choice in many cases), then I am counting on more than what
the standard gives me. If I am willing to count on "more than what the
standard gives me," then -2147483648 will work, at least in contexts
where its unexpected type will not cause immediate problems.
In real life, we DO count on more than just what the standard
guarantees. For example, most of my applications would not work if the
compiler inserted a five minute empty loop into the generated code for
each statement. Such an implementation, however, would be fully
conformant to the standard. (My thanks to Steve Clamage for the
example.) In real life, I count on standards (C++, Posix, etc.), vendor
specifications (ILog Views, HP OpenView, etc.) and also, to a certain
degree, that my suppliers are "reasonable" (no five minute loops per
statement).
All I'm trying to say is that I feel the requirement that -2147483648
give the expected results is adequately covered by the latter
condition. I am not opposed to requiring it to work, provided that such
a requirement doesn't break other things, introduce additional
complexities in the language, etc., etc. My gut feeling is that it
will. I don't consider the problem serious enough to be worth my time
and effort to find a "perfect" solution, and in fact, I seriously doubt
that a "perfect" (or even a better) solution exists.
I've addressed the two proposals in another posting, so I won't talk
about them here. If you think that the problem is real, and serious,
make a concrete proposal; if there are no other problems with it, I
won't oppose it. (Note that I consider the fact that an int may have a
value not in the range INT_MIN...INT_MAX unacceptable. And that the
expression -2147483648UL must be unsigned.)
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: willhall@idt.net (Will Hall)
Date: 1997/03/18 Raw View
In one recent post, James Kanze <james-albert.kanze@vx.cit.alcatel.fr> wrote:
> I will repeat: entering -2147483647-1 doesn't buy you anything over
> entering -2147483648. If INT_MIN (or LONG_MIN) == -2147483647, the
> results are not representable, and thus undefined. And in the usual
> cases, just entering the value as such will give the correct results.
>
> --
> James Kanze
Here are the problems I see with that argument:
(1) On 32-bit implementations, INT_MIN (or LONG_MIN) is typically
-2147483648 (i.e., -2^31), _not_ -2147483647 (i.e., -2^31 - 1). The draft
standard clearly supports the notion that -21474836748 (specified, e.g.,
as -21474836747 - 1) is representable on such systems.
(2) When it is stated that correct results will be obtained "in the usual
cases", the C++ standard, which addresses "all implementations" or "all
implementations which share some well-recognized attributes (e.g., int and
long the same size and >= 32 bits)" is _not_ being addressed.
So, to correct the misinformation in the above quoted excerpt: on
implementations with 32-bit int and long, the value -2^31 can be specified
according to the draft standard as -21474836747 - 1, or as -21474836746 -
2, and so forth; however, the value can _not_ be specified directly as
-21474836748 without triggering a clause (loophole?) in the standard which
grants implementations the freedom to perform a step that causes the
resultant value to be "implementation-defined", i.e., non-portable _even_
between two 32-bit implementations.
-Will Hall
willhall@idt.net
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: David R Tribble <david.tribble@central.beasys.com>
Date: 1997/03/18 Raw View
Abhishek Chauhan <Abhishek.Chauhan@eng.sun.com> asked:
> BTW-1, are there any languages that treat the "-" sign as part of the
> literal and consequently "-1" as a single token?
COBOL allows a leading '+' or '-' on numeric literals. It can do this
because it requires spaces to separate operators. For example:
compute sum = a * -1.50 + -0.75
This cannot be written without the spaces, so the following is illegal:
compute sum=a*-1.50+-0.75
C and C++ do not require spaces between tokens (only between keyword/identifier
tokens), so they cannot distinguish between these sequences of tokens:
sum = a - 1 + 2;
sum =a -1 +2;
I think there's been enough said in this thread. Anyone else agree?
-- David R. Tribble, david.tribble@central.beasys.com --
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: fjh@murlibobo.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/03/18 Raw View
James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:
>Specifying -2147483648 directly works portably for all implementations
>which have a representation for this value.
Are you sure? Why?
I wouldn't be too surprised if some implementations either
(a) reported errors when compiling in strict conformance mode
or (b) wrapped 2147483648 (0xf000000) around to -2147483648,
and then negated it to get a final result of zero.
Incidentally, I have written such a program that generates C code,
so this is not merely an academic question!
(Note that writing unknown floating point values also poses problems
for programs that generate C code: the possibility of IEEE infinity
and NaN mean that you can't be sure that the output of `printf("%f", x)'
or `cout << x' will be valid C syntax.)
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/19 Raw View
willhall@idt.net (Will Hall) writes:
|> In article <rf5endeu703.fsf@vx.cit.alcatel.fr>, James Kanze
|> <james-albert.kanze@vx.cit.alcatel.fr> wrote:
|>
|> > Specifying -2147483648 directly works portably for all implementations
|> > which have a representation for this value.
|>
|> Does it? Here's an excerpt from one of your earlier posts:
|>
|> > On typical compilers, for typical 2's complement 32 bit machines, the
|> > results ...
|>
|> [ of `int i = -2147483648;' ]
|>
|> > ... are exactly what is expected, even if they are arrived at by a
|> > round-about means.
|> >
|> > It is true that this is only "typical" behavior, and not guaranteed by
|> > the standard. But the standard doesn't guarantee that there is any type
|> > in which -2147483648 can be represented, so you can't use this constant
|> > in a portable program anyway, no matter how the lexer scans it.
So where is the contradiction.
Using -2147483648 is not portable, according to the standard. I think
everyone agrees here; an implementation is not even required to be able
to represent the value (and a 32 bit 1's complement will not represent
it). Given that, all you can talk about is real compilers, not the
standard; in real life, the number is portable to all machines on which
it is representable.
The guarantee obviously isn't in the standard, since the standard says
that the number may not even be representable. This doesn't mean that
it won't work *IF* you limit the category of machines to which you will
port to those that do support it. And in practice, all 2's complement
machines will support it; the number of implementations where it won't
work will be extremely small.
[Correct analysis deleted...]
|> (3) Now we need to initialize an int (i) using an unsigned long int (2^31,
|> or 2147483648). From 4.7[3], we see that "the value is
|> implementation-defined".
It is implementation-defined if the value is even representable. No one
is arguing that. What I said was:
|> > Specifying -2147483648 directly works portably for all implementations
|> > which have a representation for this value.
Obviously, this is NOT from the standard; since the standard doesn't
even allow the value in portable programs, it doesn't address the
problem of representation.
But I didn't say that "the standard guarantees...". I said that "[it]
works...". If you are writing code that rigorously conforms to the
standard, you will not use the value, period. If you are writing code
that targets a particular subset of implementations (e.g.: 2's
complement), your code IS implementation dependant, so what is the
objection to being dependant on implementation dependant behavior?
In theory, a 2's complement implementation *could* fail, say by using 0
for all values that don't fit. In practice, it won't, because it means
a lot of extra work for the compiler just to break a significant number
of programs.
|> So, we have an example of a (familiar) class of implementations (namely,
|> those with 32-bit int and 32-bit long) that have a representation for
|> -2147483648 but that do _not_ allow for this value's direct specification.
Except that they do allow it.
If my statement is wrong, it is remarkably easy to disprove: just show
an implementation where it doesn't work.
I know that this has nothing to do with the standard, but if you use
such a value, you are outside of the guarantees of the standard anyway.
|> If Mr. Kanze or anyone else is able to refute this reading of the draft
|> standard, I urge that person to set the world straight on the matter.
The reading of the standard has nothing to do with it. If you want to
conform rigorously to the standard, you cannot even use the value, so
the question of how to represent it is moot.
|> Otherwise, Mr. Kanze, though you may find the discussion in this thread
|> boring (as you indicate in your most recent post), you may wish to try to
|> keep from contradicting yourself in your many posted contributions to it.
|> ;)
What is getting boring is that I am repeating myself. Apparently, I
wasn't clear. If you stick rigorously within the standard, there is no
problem, since the value cannot occur. If you are practically concerned
with portability, there is no problem, since the obvious expression
works in all cases where the value is representable.
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/19 Raw View
Marcelo Cantos <marcelo@mds.rmit.edu.au> writes:
|> James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:
|>
|> > This is getting boring, but there is no need to go through this.
|> > Specifying -2147483648 directly works portably for all implementations
|> > which have a representation for this value.
|>
|> Then here's something to alleviate the boredom. Try compiling the
|> following (on a compiler with 32-bit int).
|>
|> void f(int);
|> void f(long);
|>
|> void g() {
|> f(-2147483647);
|> f(-2147483648);
|> }
|>
|> And see how far you get!
Finally a reasonable point. (Excellent, even.) The second is, of
course, ambiguous. Which is certainly counter-intuitive, if nothing
else.
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/19 Raw View
Abhishek Chauhan <Abhishek.Chauhan@eng.sun.com> writes:
[I've cut a lot, since I've addressed most points in another
posting...]
|> It appears that you have misread my post.
Agreed. I thought that you were talking about writing the value out,
then simple reading it back in again.
|> In a separate posting on the same subject, you have mentioned:
|> James Kanze wrote:
|> > This is getting boring, but there is no need to go through this.
|> > Specifying -2147483648 directly works portably for all
|> > implementations which have a representation for this value. And
|> > specifying -2147483647-1 doesn't work if the implementation cannot
|> > represent the results.
|>
|> I agree to your former assertion that it is getting boring. But I
|> believe you are not correct in the latter assertion. It is not that
|> specifying -2147483648 directly, works portably, just that it
|> **happens** to work "portably". Which is a _different_ thing than it
|> being *guaranteed* to work portably. I base my statement on the
|> following excerpt from one of Will Hall's prior posting.
It is obviously not "required" to work portably, since the standard
doesn't even guarantee that the value exists. It is equally obvious, I
hope, that code which strives for 100% portability will not use this
value. On the other hand, if the value **happens** to be there, the
natural way of using it **happens** to work. That the natural way of
specifying this value happens to work is, of course, not guaranteed by
the standard. But neither is the fact that the value happens to be
there.
If you are really writing portable code, you won't use the value. And
if you're not writing portable code, what the target implementations
actually do (and are certain to do in the future) would seem to me to be
a sufficient guarantee.
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/19 Raw View
willhall@idt.net (Will Hall) writes:
|> In one recent post, James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
|> wrote:
|> > I will repeat: entering -2147483647-1 doesn't buy you anything over
|> > entering -2147483648. If INT_MIN (or LONG_MIN) == -2147483647, the
|> > results are not representable, and thus undefined. And in the usual
|> > cases, just entering the value as such will give the correct results.
|>
|> Here are the problems I see with that argument:
|>
|> (1) On 32-bit implementations, INT_MIN (or LONG_MIN) is typically
|> -2147483648 (i.e., -2^31), _not_ -2147483647 (i.e., -2^31 - 1). The draft
|> standard clearly supports the notion that -21474836748 (specified, e.g.,
|> as -21474836747 - 1) is representable on such systems.
|>
|> (2) When it is stated that correct results will be obtained "in the usual
|> cases", the C++ standard, which addresses "all implementations" or "all
|> implementations which share some well-recognized attributes (e.g., int and
|> long the same size and >= 32 bits)" is _not_ being addressed.
And the problem I see with your argument is that the standard doesn't
even guarantee that the value exists. If we are arguing about the
standard, and 100% portable code, then the negative value -2147483648
cannot occur, regardless of how you specify it.
I agree that the implementations which will not support the value
-2147483648 are rare, rare enough that if the implementation needs the
value, it might be an acceptable compromise to forgo portability to
these implementations. Would you not admit, however, that exactly the
same argument holds for writing the literal -2147483648, and not using
some other fancy work-around.
|> So, to correct the misinformation in the above quoted excerpt: on
|> implementations with 32-bit int and long, the value -2^31 can be specified
|> according to the draft standard as -21474836747 - 1, or as -21474836746 -
|> 2, and so forth; however, the value can _not_ be specified directly as
|> -21474836748 without triggering a clause (loophole?) in the standard which
|> grants implementations the freedom to perform a step that causes the
|> resultant value to be "implementation-defined", i.e., non-portable _even_
|> between two 32-bit implementations.
To correct the misinformation in the above excerpt: the value -2^32
cannot appear in a portable program. Period. The "loophole" which
triggers "implementation-defined" is the presence of the value, not the
way it is written.
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/19 Raw View
fjh@murlibobo.cs.mu.OZ.AU (Fergus Henderson) writes:
|> James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:
|>
|> >Specifying -2147483648 directly works portably for all implementations
|> >which have a representation for this value.
|>
|> Are you sure? Why?
Yes. Because compiler vendors do it for money, and breaking customer
code just because the standard says you can is not generally a
profittable undertaking.
|> I wouldn't be too surprised if some implementations either
|> (a) reported errors when compiling in strict conformance mode
I wouldn't like an error, but I would certainly expect a warning. It's
not portable, since the resulting value is not representable on some
machines.
As I said in an other posting, portable code won't use this value.
|> or (b) wrapped 2147483648 (0xf000000) around to -2147483648,
|> and then negated it to get a final result of zero.
Unless I'm badly mistaken, in 32 bit 2's complement (the only
implementations which pose a problem, I think), 2147483648 is
0x80000000; at the hardware level, the usual implementation negation is
to complement (0x7fffffff) and then increment (0x80000000). Which is
-2147483648, interpreted as a signed 32 bit value.
I am fairly certain that in fact, all implementations do this. Which is
why it works.
The one case where it could cause a problem is if the machine traps on
signed overflow. Except that when the negate takes place, we are still
in unsigned mode, and the results are well defined.
Theoretically, the conversion to signed could cause a problem; in
practice, I feel safe in saying that it won't. If you don't care enough
about strict conformance and portability to avoid this value (as being
potentially non-representable), then you shouldn't have any problem with
the fact that the conversion from unsigned is implementation defined
either.
|> Incidentally, I have written such a program that generates C code,
|> so this is not merely an academic question!
Worrying about the results of -2147483648, on a 2's complement machine,
is, IMHO, an academic question.
|> (Note that writing unknown floating point values also poses problems
|> for programs that generate C code: the possibility of IEEE infinity
|> and NaN mean that you can't be sure that the output of `printf("%f", x)'
|> or `cout << x' will be valid C syntax.)
This is, of course, a real problem. Even without the IEEE special
values, there is no real guarantee that the compiler will generate the
exact same values you were outputting. (The standard really doesn't
guarantee much of anything concerning floating point.)
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: David R Tribble <david.tribble@central.beasys.com>
Date: 1997/03/19 Raw View
fjh@murlibobo.cs.mu.OZ.AU (Fergus Henderson) wrote:
> >Specifying -2147483648 directly works portably for all implementations
> >which have a representation for this value.
>
> Are you sure? Why?
> I wouldn't be too surprised if some implementations either
> (a) reported errors when compiling in strict conformance mode
> or (b) wrapped 2147483648 (0xf000000) around to -2147483648,
> and then negated it to get a final result of zero.
Nope. On 32-bit two's-complement machines, -(-2147483648) is -2147483648,
not zero. I.e., -0x80000000 is 0x80000000, similar to the fact that -0 is 0.
However, the point should be made that '-2147483648' is two tokens, the
second of which is the numeric literal '2147483648'. This value is too big
to be represented as a 32-bit signed binary value, so the compiler will
accept it but only as an unsigned quantity. Thus '-2147483648' is an
unsigned (!) integer expression (equal to 0x80000000).
The expression '(-2147483647-1)' does not suffer from this and results in a
signed value (equal to 0x80000000).
Of course, you could use the expression '-(signed)2147483648' instead,
but then you couldn't use this value in preprocessor #if directives.
-- David R. Tribble, david.tribble@central.beasys.com --
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: James Kuyper <kuyper@wizard.net>
Date: 1997/03/20 Raw View
James Kanze wrote:
...
> |> [ of `int i = -2147483648;' ]
...
> What is getting boring is that I am repeating myself. Apparently, I
> wasn't clear. If you stick rigorously within the standard, there is no
> problem, since the value cannot occur. If you are practically concerned
> with portability, there is no problem, since the obvious expression
> works in all cases where the value is representable.
The standard could guarantee that such expressions work in all cases
where their value is representable, while leaving the result undefined
in other cases. The fact that there is no such guarantee is a
consequence of two features of the standard: integer literals cannot be
negative, and the conversion of unsigned integers to signed integers is
completely undefined. Change either feature, and the standard would
provide an implicit guarantee, that would only apply to cases where the
value is representable.
I understand the reasons for each feature, but I don't like either one,
and I don't like this consequence. Maybe an explicit guarantee would be
appropriate, with the details of making it consistent with the other two
features being left in the implementor's hands? The undefined behavior
for signed conversions could include behavior that makes this work
right, even on machines where such behavior is not the 'natural'
behavior.
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: willhall@idt.net (Will Hall)
Date: 1997/03/20 Raw View
In article <2.2.32.19970319175303.002e6020@central.beasys.com>, David R
Tribble <david.tribble@central.beasys.com> wrote:
> fjh@murlibobo.cs.mu.OZ.AU (Fergus Henderson) wrote:
> > >Specifying -2147483648 directly works portably for all implementations
> > >which have a representation for this value.
> >
> > Are you sure? Why?
> > I wouldn't be too surprised if some implementations either
> > (a) reported errors when compiling in strict conformance mode
> > or (b) wrapped 2147483648 (0xf000000) around to -2147483648,
> > and then negated it to get a final result of zero.
>
> Nope. On 32-bit two's-complement machines, -(-2147483648) is -2147483648,
> not zero. I.e., -0x80000000 is 0x80000000, similar to the fact that -0 is 0.
>
> However, the point should be made that '-2147483648' is two tokens, the
> second of which is the numeric literal '2147483648'. This value is too big
> to be represented as a 32-bit signed binary value, so the compiler will
> accept it but only as an unsigned quantity. Thus '-2147483648' is an
> unsigned (!) integer expression (equal to 0x80000000).
^^^^^^^^^^^^^^^^^^^^
[ Or, to be absolutely accurate as per 2.13.1[2], `unsigned long'. ]
Yes, that point has been made already (a few times) in this thread, and it
is IMHO a good one. Furthermore, an attempt to convert 0x80000000 to a
signed value on such an implementation is implementation-defined, so that,
e.g., `int i = -0x80000000;' will initialize i in an
implementation-defined manner; in particular, it may initialize it to a
value different from the value i receives in an assignment such as `int i
= -0x7fffffff - 1;', whose value (on a system with ints capable of
representing -2^31) is mandated by the standard.
> The expression '(-2147483647-1)' does not suffer from this and results in a
> signed value (equal to 0x80000000).
>
> Of course, you could use the expression '-(signed)2147483648' instead ...
^^^^^^^^^^^^^^^^^^^
Actually, you can _not_ use this as a reliable substitute for
(-2147483647-1) on systems where representable ints range from -2^31 to
2^31 - 1, as the conversion of 2147483648 (which, as you point out, is of
an unsigned type on such systems) to `signed' is implementation-defined
according to 4.7[3].
-Will Hall
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: willhall@idt.net (Will Hall)
Date: 1997/03/20 Raw View
In article <rf5endcfbnb.fsf@vx.cit.alcatel.fr>, James Kanze
<james-albert.kanze@vx.cit.alcatel.fr> wrote:
> willhall@idt.net (Will Hall) writes:
>
> |> In one recent post, James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
> |> wrote:
> |> > I will repeat: entering -2147483647-1 doesn't buy you anything over
> |> > entering -2147483648. If INT_MIN (or LONG_MIN) == -2147483647, the
> |> > results are not representable, and thus undefined. And in the usual
> |> > cases, just entering the value as such will give the correct results.
> |>
> |> Here are the problems I see with that argument:
> |>
> |> (1) On 32-bit implementations, INT_MIN (or LONG_MIN) is typically
> |> -2147483648 (i.e., -2^31), _not_ -2147483647 (i.e., -2^31 - 1). The draft
> |> standard clearly supports the notion that -21474836748 (specified, e.g.,
> |> as -21474836747 - 1) is representable on such systems.
> |>
> |> (2) When it is stated that correct results will be obtained "in the usual
> |> cases", the C++ standard, which addresses "all implementations" or "all
> |> implementations which share some well-recognized attributes (e.g., int and
> |> long the same size and >= 32 bits)" is _not_ being addressed.
>
> And the problem I see with your argument is that the standard doesn't
> even guarantee that the value exists. If we are arguing about the
> standard,
We are.
> ... and 100% portable code,
We are not -- as you interpret it, that would be a foolish thing to argue
about (esp. in the context of negative integer literals), as it would
exclude discussion of many interesting & important issues that arise only
for a proper subset (however practically relevant) of all possible
implementations. The practically relevant subset about which _I_ have been
arguing in recent posts is that set of conforming implementations which
have the following properties: representable int and long range from -2^31
to 2^31 - 1, and representable unsigned long ranges from 0 to 2^32 - 1.
Let us call this "The two's-complement-like 32-bit subset", or "The tcl32
subset".
[BTW, another interesting subset is that selected by the following
properties: int & long from -2^63 to 2^63 - 1, unsigned long from 0 to
2^64 - 1. Let us call this "The tcl64 subset". Of particular interest IMO
is the interface between the tcl64 subset and the above-mentioned tcl32
subset. For example, although -2^31 is representable as an int on the
union of these two subsets, it is directly specifiable as -2147483648 only
on the tcl64 subset.]
> ... then the negative value -2147483648
> cannot occur, regardless of how you specify it.
Yes, but the point you are making is IMHO irrelvant to the discussion it
attempts to address.
> I agree that the implementations which will not support the value
> -2147483648 are rare, rare enough that if the implementation needs the
> value, it might be an acceptable compromise to forgo portability to
> these implementations. Would you not admit, however, that exactly the
> same argument holds for writing the literal -2147483648, and not using
> some other fancy work-around.
Sorry, you lost me there ... I don't follow your argument, so I can't
admit anything based upon it just yet.
> To correct the misinformation in the above excerpt: the value
> -2^32 cannot appear in a portable program. Period.
^^^^^
[ Presumably, you mean -2^31, as the appearance of -2^32 was not being
adressed in that post ... while your assertion holds for -2^32 in the
context of this discussion (tcl32 subset), it does _not_ hold for -2^31. ]
Not according to the absurdly restrictive interpretation of "portable"
which you seem to be employing. If we were to make the friendly agreement
that, in the context of discussion of the specifiability of -2^31 as
-2147483648 versus -2147483647 - 1, assertions regarding portability and
anything else shall (unless it is explicitly indicated otherwise) be taken
to refer to the contextually relevant subset of all conforming
implementations tcl32 detailed above, then these several consequences
would follow from the draft standard:
(1) the value -2^31 is representable.
(2) the expression (-2147483647 - 1) is a portable (if indirect) means of
specifiying -2^31. The same holds for all expressions (-x - y) where x and
y are integer literals (as defined in the draft, i.e., not preceded by a
sign) with 0 <= x <= 2^31 - 1 and y equal to (2^31 - x).
(3) the character sequence `-2147483648' is comprised of two tokens (the
unary negation operator followed by 2147483648), and there does not exist
a usage of it which is guaranteed to yield a particular value of type int;
in particular, the standard says that the value of each of these
expressions is implementation-defined:
(a) (int) -2147483648
(b) i = -2147483648 /* where i is of type int */
> ... The "loophole" which
> triggers "implementation-defined" is the presence of the value, not the
> way it is written.
Wrong for the context relevant to this discussion.
> From a practical point of view, if the implementation supports the value
> -2^32, it will also allow it to be written -21474836748.
If you really meant -2^32, then the above statement is correct but
irrelevant. If you meant -2^31, it is relevant but incorrect.
-Will Hall
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: willhall@idt.net (Will Hall)
Date: 1997/03/20 Raw View
In article <rf5k9n4fdez.fsf@vx.cit.alcatel.fr>, James Kanze
<james-albert.kanze@vx.cit.alcatel.fr> wrote:
> willhall@idt.net (Will Hall) writes:
>
> |> In article <rf5endeu703.fsf@vx.cit.alcatel.fr>, James Kanze
> |> <james-albert.kanze@vx.cit.alcatel.fr> wrote:
> |>
> |> > Specifying -2147483648 directly works portably for all implementations
> |> > which have a representation for this value.
> |>
> |> Does it? Here's an excerpt from one of your earlier posts:
> |>
> |> > On typical compilers, for typical 2's complement 32 bit machines, the
> |> > results ...
> |>
> |> [ of `int i = -2147483648;' ]
> |>
> |> > ... are exactly what is expected, even if they are arrived at by a
> |> > round-about means.
> |> >
> |> > It is true that this is only "typical" behavior, and not guaranteed
> |> > by the standard. But the standard doesn't guarantee that there is
> |> > any type in which -2147483648 can be represented, so you can't use
> |> > this constant in a portable program anyway, no matter how the lexer
> |> > scans it.
>
> So where is the contradiction.
I will rephrase your statements to preserve meaning but elucidate the
contradiction:
Stmt 1: For that subset of all conforming implementations on which
-2147483648 can be represented as a value of type int, it can be specified
as `-2147483648'.
Stmt 2: The C++ statement `int i = -2147483648;' has results on typical
2's complement 32 bit machines which are not guaranteed by the standard.
Stmt 1 contradicts stmt 2, principally because stmt 1 is false. Stmt 2 is
true according to reasonable interpretations of the word `typical'.
DEFINITION: By "tcl32 subset" (which stands for "two's-complement-like
32-bit subset") we shall mean the subset of all conforming implementations
for which int and long range from -2^31 to 2^31 - 1, and for which
unsigned long ranges from 0 to 2^32 - 1. [Note: this has been a
particularly relevant subset, practically speaking, throughout much of the
1990's.]
ASSERTIONS for the tcl32 subset:
[1] The value -2^31 is representable.
[2] The expression -2147483648, converted (by standard conversion or
otherwise) to type int, has a value that is implementation-defined.
[3] By [1] and [2], -2^31 is representable but attempting to specify it
directly as -2147483648 does not "work" -- i.e., it results in an
implementation-defined value and not the value -2^31 which one might
"expect".
> Using -2147483648 is not portable, according to the standard.
This assertion is true only in an absurdly narrow sense which excludes the
context in which the current discussion is taking place; hence the
assertion is irrelevant.
> I think
> everyone agrees here;
Think again ;)
> ... Given that, all you can talk about is real compilers, not the
> standard;
Ah, interesting! So the standard has nothing to do with real compilers, eh?
> ... in real life, the number is portable to all machines on which
> it is representable.
If you are referring to the number -2^31, you are mistaken.
> The guarantee obviously isn't in the standard, since the standard says
> that the number may not even be representable.
Again, irrelevant in the context of the current discussion. Come on,
James! Can you really be in earnest here?
> What I said was:
>
> |> > Specifying -2147483648 directly works portably for all
> |> > implementations which have a representation for this value.
>
> Obviously, this is NOT from the standard ...
Obviously -- for one thing, what you said is false.
> But I didn't say that "the standard guarantees...". I said that "[it]
> works...".
The statement that "it works" is false, too.
> If you are writing code that rigorously conforms to the
> standard, you will not use the value, period.
This sort of rigorous conformity is irrelevant in the context of the
current discussion.
> If you are writing code
> that targets a particular subset of implementations (e.g.: 2's
> complement), your code IS implementation dependant, so what is the
> objection to being dependant on implementation dependant behavior?
That said subset is an extremely relevant subset, and that for the
impending advent of implementations (yes, "real world" implementations)
within the tcl64 subset (analogous to tcl32 but for 64-bits -- see my
other post detailing this) the behavior of -2147483648 is _not_
implementation-defined but rather is determined by the standard.
Therefore, behavior at the interface of the tcl32 and tcl64 subsets is of
special "real world" interest to anyone who cares about minimizing
confusion and maximizing portability.
> In theory, a 2's complement implementation *could* fail, say by using 0
> for all values that don't fit.
Yes, it could -- in fact, _any_ implementation whose int, long and
unsigned long types have a range no greater than for implementations in
the tcl32 subset is given a LICENSE to fail by the draft standard.
> In practice, it won't, because it means
> a lot of extra work for the compiler just to break a significant number
> of programs.
No offense, Mr. Kanze, but I for one would rather have that secured by the
standard than by an assurance from you.
> |> So, we have an example of a (familiar) class of implementations (namely,
> |> those with 32-bit int and 32-bit long) that have a representation for
> |> -2147483648 but that do _not_ allow for this value's direct
> |> specification.
>
> Except that they do allow it.
I trust that I have made myself even clearer than before on this point,
and will refrain from repeating myself yet again.
> If my statement is wrong, it is remarkably easy to disprove: just show
> an implementation where it doesn't work.
Not necessary: to prove your statement wrong (i.e., the stmt that, in
effect, "implementations in the tcl32 subset allow direct specification of
an int using the 2-token character sequence `-2147483648'") was even
easier; all I had to do (see above) was to cite the draft standard.
> I know that this has nothing to do with the standard, but if you use
> such a value, you are outside of the guarantees of the standard anyway.
Only in an absurdly (i.e., counterproductively) pedantic way.
> If you stick rigorously within the standard, there is no
> problem, since the value cannot occur.
Ditto.
> If you are practically concerned
> with portability, there is no problem, since the obvious expression
> works in all cases where the value is representable.
False.
-Will Hall
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Marcelo Cantos <marcelo@mds.rmit.edu.au>
Date: 1997/03/16 Raw View
Abhishek Chauhan <Abhishek.Chauhan@eng.sun.com> writes:
>
> Marcelo Cantos wrote:
> > The reality is that when the programmer wants to type -2147483648, it
> > is usually because he wants the lowest possible integer value, in
> > which case, INT_MIN is the better choice.
>
> I can think of "realities" where INT_MIN crops up out of computations,
> and where it matters how you write it.
Rare (very rare, I would speculate), and still solvable, as you have
shown.
> Instead (s)he would have to rise to the occasion and write:
>
> if (bitmap.bits[i] == INT_MIN)
> cout << "INT_MIN";
> else
> cout << bitmap.bits[i];
Which is far better than demanding that lexers be designed to
accomodate negative literals. How would you implement a lexer that
interprets `(Foo)-2' as three tokens if Foo is a class and four if
it's a variable? This is vaguely like the problem of determining
whether the sequence `a b(c);' is a function declaration or a class
instantiation, only worse since it requires the lexer to resolve the
ambiguity rather the parser.
--
______________________________________________________________________
Marcelo Cantos, Research Assistant __/_ marcelo@mds.rmit.edu.au
Multimedia Database Systems Group, RMIT / _ Tel 61-3-9282-2497
723 Swanston St, Carlton VIC 3053 Aus/ralia ><_> Fax 61-3-9282-2490
Acknowledgements: errors - me; wisdom - God; funding - RMIT
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/17 Raw View
Abhishek Chauhan <Abhishek.Chauhan@eng.sun.com> writes:
|> Marcelo Cantos wrote:
|> > The reality is that when the programmer wants to type -2147483648, it
|> > is usually because he wants the lowest possible integer value, in
|> > which case, INT_MIN is the better choice.
|>
|> I can think of "realities" where INT_MIN crops up out of computations,
|> and where it matters how you write it.
|>
|> Consider some program that _generates_ C code. Say something like
|> xbitmap. xbitmap saves bitmap images as C header files. The file
|> contains a C-statement that initializes an array with the bits of the
|> bitmap. This allows you to include the file into your GUI code and
|> have the bitmap compiled into your program.
|>
|> If a simple xbitmap programmer were to write something like -
|>
|> cout << bitmap.bits[i];
|>
|> to write out the bitmap bits, it would be an error when the resulting
|> "header file" is included in a C program, if one of the bitmap bits
|> happened to be same as the INT_MIN! (because it would be written out
|> as -2147483648, which, pedantically speaking, is not INT_MIN)
Could you please explain the reasoning behind this conclusion. At least
the previous posters were starting from something in the standard (that
an integral literal cannot be negative), even if their conclusions were
wrong. In the case of IO, however, the formatters definitely do treat a
minus sign as an integral part of the value.
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/17 Raw View
willhall@idt.net (Will Hall) writes:
|> In article
|> <bg67yubsuc.fsf@janus.i-have-a-misconfigured-system-so-shoot-me>, Marcelo
|> Cantos <marcelo@mds.rmit.edu.au> wrote:
|>
|> > Why not...
|> >
|> > #define INT32_MIN (-2147483647-1)
|> >
|> > In one of your header files!
|>
|> You're absolutely right -- AFAIK, this is currently the way to minimize
|> the number of times one has to use the -X-1 specification in a program.
|>
|> > ... Now that isn't so hard is it?
|>
|> It's not hard if the programmer in question is already aware of the
|> language quirk (shortcoming?) that necessitates such practice. How about
|> for the programmer who encounters this feature for the first time,
|> diiscovering it only after having _naively_ assumed that a 32-bit
|> implementation (which is not _required_ to have -2147483648 be what it
|> looks like) would support simple direct specification of all values of one
|> of its built-in types?
This is getting boring, but there is no need to go through this.
Specifying -2147483648 directly works portably for all implementations
which have a representation for this value. And specifying
-2147483647-1 doesn't work if the implementation cannot represent the
results.
|> [Also, perhaps no one else takes this view, but wouldn't anyone out there
|> feel the slightest bit _embarrassed_ for a standard that _necessitated_
|> such a roundabout means of specifying a constant int value perfectly
|> representable by a given implementation?]
I would consider it totally unacceptable for the standard to require
such a round-about way of specifying an int value that was supported.
But the current draft doesn't require it, so where is the problem?
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: willhall@idt.net (Will Hall)
Date: 1997/03/17 Raw View
In article <rf5endeu703.fsf@vx.cit.alcatel.fr>, James Kanze
<james-albert.kanze@vx.cit.alcatel.fr> wrote:
> Specifying -2147483648 directly works portably for all implementations
> which have a representation for this value.
Does it? Here's an excerpt from one of your earlier posts:
> On typical compilers, for typical 2's complement 32 bit machines, the
> results ...
[ of `int i = -2147483648;' ]
> ... are exactly what is expected, even if they are arrived at by a
> round-about means.
>
> It is true that this is only "typical" behavior, and not guaranteed by
> the standard. But the standard doesn't guarantee that there is any type
> in which -2147483648 can be represented, so you can't use this constant
> in a portable program anyway, no matter how the lexer scans it.
[ BTW, you can certainly use the value -2^31, once you manage to specify
it, on that subset of all conforming implementations for which int has 32
bits or more.]
So which one of these two mutually exclusive positions have you decided
upon? Personally, I agree with the earlier one (i.e., second one above) --
even on implementations which are capable of representing -2147483648, the
draft standard does not guarantee that a program specifying it as such
(i.e., as `-2147483648') will port to another implementation that is also
capable of representing that number. For the second time in this thread, I
will cite how the draft treats `int i = -2147483648;' for an
implementation with 32-bit int and long:
(1) the literal 2147483648 (synonymous herein with 2^31), too large to be
an int, is taken (2.13.1[2]) as an unsigned long int.
(2) since the literal quantity achieved in (1) is unsigned, unary `-'
(5.3[7]) subtracts it from 2^n (where n == the # of bits in the type of the
operand [unsigned long int] == 32), yielding 2^32 - 2^31 = 2^31 with
type unsigned long int (still from 5.3[7]). (Thus the net effect of the
unary negation is nil.)
(3) Now we need to initialize an int (i) using an unsigned long int (2^31,
or 2147483648). From 4.7[3], we see that "the value is
implementation-defined".
So, we have an example of a (familiar) class of implementations (namely,
those with 32-bit int and 32-bit long) that have a representation for
-2147483648 but that do _not_ allow for this value's direct specification.
If Mr. Kanze or anyone else is able to refute this reading of the draft
standard, I urge that person to set the world straight on the matter.
Otherwise, Mr. Kanze, though you may find the discussion in this thread
boring (as you indicate in your most recent post), you may wish to try to
keep from contradicting yourself in your many posted contributions to it.
;)
Will Hall
(willhall@idt.net)
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/18 Raw View
Marcelo Cantos <marcelo@mds.rmit.edu.au> writes:
|> willhall@idt.net (Will Hall) writes:
|>
|> >
|> > In article <01bc2fbf$98f0ace0$e56dadce@azguard>, "Bradd W. Szonye"
|> > <Nutty_Irishman@msn.com> wrote:
|> >
|> > >Well, maybe a programmer can't write "-2147483648" in a portable program,
|> > >but the library implementers can use it to write "INT_MIN" or "LONG_MIN" if
|> > >necessary.
|> >
|> > As I noted in an earlier post, INT_MIN and LONG_MIN will not necessarily
|> > be constant across implementations with, say, 32-bit and 64-bit int,
|> > whereas `-2147483648' would be if it were portably representable on 32-bit
|> > systems.
|>
|> Why not...
|>
|> #define INT32_MIN (-2147483647-1)
|>
|> In one of your header files! Now that isn't so hard is it? Good
|> programming practice would mandate this anyway, since it more clearly
|> states your intention, even if you *could* type it as a simple
|> literal.
I will repeat: entering -2147483647-1 doesn't buy you anything over
entering -2147483648. If INT_MIN (or LONG_MIN) == -2147483647, the
results are not representable, and thus undefined. And in the usual
cases, just entering the value as such will give the correct results.
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Abhishek Chauhan <Abhishek.Chauhan@eng.sun.com>
Date: 1997/03/18 Raw View
James Kanze wrote:
> Abhishek Chauhan <Abhishek.Chauhan@eng.sun.com> writes:
[description of xbitmap snipped]
> |> If a simple xbitmap programmer were to write something like -
> |>
> |> cout << bitmap.bits[i];
> |>
> |> to write out the bitmap bits, it would be an error when the resulting
> |> "header file" is included in a C program, if one of the bitmap bits
> |> happened to be same as the INT_MIN! (because it would be written out
> |> as -2147483648, which, pedantically speaking, is not INT_MIN)
>
> Could you please explain the reasoning behind this conclusion. At least
> the previous posters were starting from something in the standard (that
> an integral literal cannot be negative), even if their conclusions were
> wrong. In the case of IO, however, the formatters definitely do treat a
> minus sign as an integral part of the value.
It appears that you have misread my post. When one writes:
cout << INT_MIN;
you state and I agree that it will output the string "-2147483648". I
have not said anything to the contrary. "the formatters definitely do
treat a minus sign as an intergral part of the value". Sure. No
problem there.
What I did say was that if you were to write something like:
cout << "int jk = " << INT_MIN << ";\n";
in one of your utilities that _generates_ C code, then what you get in
the resulting file looks like:
int jk = -2147483648;
And when you try to compile this code, that your utility has
_generated_, you run into the issue being discussed in this thread --
"Negative integer literals". So please add me to the list of posters
who were "starting from something in the standard" :-)
In a separate posting on the same subject, you have mentioned:
James Kanze wrote:
> This is getting boring, but there is no need to go through this.
> Specifying -2147483648 directly works portably for all
> implementations which have a representation for this value. And
> specifying -2147483647-1 doesn't work if the implementation cannot
> represent the results.
I agree to your former assertion that it is getting boring. But I
believe you are not correct in the latter assertion. It is not that
specifying -2147483648 directly, works portably, just that it
**happens** to work "portably". Which is a _different_ thing than it
being *guaranteed* to work portably. I base my statement on the
following excerpt from one of Will Hall's prior posting.
Will Hall wrote:
> However, as to Kanze's characterization of the exclusion of
> negatives from the set of allowed integer literals as resulting in
> "simplicity" (see below), I would like to provide an interesting
> example (similar to one posted by Fergus Henderson -- also see below
> -- but with a different emphasis):
> int i = -2147483648; // -2^31 is the desired initializer
> (1) Assuming for argument's sake that int and long are both 32-bit
> types, the literal 2147483648 (colloquially, 2^31), too large to be
> an int, is taken (2.13.1[2]) as an unsigned long int.
> (2) As the literal quantity achieved in (1) is unsigned, unary `-'
> (5.3[7]) subtracts it from 2^n, where n (the # of bits in the type
> of the operand, unsigned long int) is 32 in this example, of the
> unsigned long int in (1). The result is (mathematically) 2^32 - 2^31
> = 2^31, and the type of the result (still from 5.3[7]) is unsigned
> long int; so the net effect of the unary negation is nil: it's a
> no-op for this particular example.
> (3) Now comes the fun part: we have an unsigned long int which we
> must use to intialize an int. Trusty 4.7[3] guides us in obtaining a
> result ... do what we like, it tells us, or (to quote) "the value is
> implementation-defined".
-abhishek
---
Abhishek Chauhan, abhishek.chauhan@sun.com
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Abhishek Chauhan <Abhishek.Chauhan@eng.sun.com>
Date: 1997/03/18 Raw View
Marcelo Cantos wrote:
> The reality is that when the programmer wants to type -2147483648, it
> is usually because he wants the lowest possible integer value, in
> which case, INT_MIN is the better choice.
Abhishek Chauhan <Abhishek.Chauhan@eng.sun.com> writes:
> I can think of "realities" where INT_MIN crops up out of computations,
> and where it matters how you write it.
[example of xbitmap--a C code generator, snipped]
Marcelo Cantos wrote:
> Rare (very rare, I would speculate), and still solvable, as you have
> shown.
A bug that occurs rarely is a bug nonetheless. Therefore I think we
both agree that if one is writing a utility that generates C code,
then one must pay special attention to the output of negative integer
literals in situations where it is not possible to assert that those
literals would never be equal to INT_MIN.
> Which is far better than demanding that lexers be designed to
> accomodate negative literals. How would you implement a lexer that
> interprets `(Foo)-2' as three tokens if Foo is a class and four if
> it's a variable? This is vaguely like the problem of determining
> whether the sequence `a b(c);' is a function declaration or a class
> instantiation, only worse since it requires the lexer to resolve the
> ambiguity rather the parser.
I agree that what we have in the standard is better than the
alternative. I am only pointing out that it is not free from all
trouble.
-abhishek
---
Abhishek Chauhan, abhishek.chauhan@sun.com
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Marcelo Cantos <marcelo@mds.rmit.edu.au>
Date: 1997/03/18 Raw View
James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:
> This is getting boring, but there is no need to go through this.
> Specifying -2147483648 directly works portably for all implementations
> which have a representation for this value.
Then here's something to alleviate the boredom. Try compiling the
following (on a compiler with 32-bit int).
void f(int);
void f(long);
void g() {
f(-2147483647);
f(-2147483648);
}
And see how far you get!
--
______________________________________________________________________
Marcelo Cantos, Research Assistant __/_ marcelo@mds.rmit.edu.au
Multimedia Database Systems Group, RMIT / _ Tel 61-3-9282-2497
723 Swanston St, Carlton VIC 3053 Aus/ralia ><_> Fax 61-3-9282-2490
Acknowledgements: errors - me; wisdom - God; funding - RMIT
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: fjh@murlibobo.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/03/18 Raw View
willhall@idt.net (Will Hall) writes:
>[ BTW, you can certainly use the value -2^31, once you manage to specify
>it, on that subset of all conforming implementations for which int has 32
>bits or more.]
That's not completely correct. One's complement implementations can
have 32-bit ints yet not be able to represent -2^31.
Mind you, I've never used a one's complement machine, and I expect that
I never will.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/13 Raw View
fjh@murlibobo.cs.mu.OZ.AU (Fergus Henderson) writes:
|> James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:
|>
|> >willhall@idt.net (Will Hall) writes:
|> >
|> >|> [Q.2] What purpose is served by the exclusion of explicitly negative
|> >|> values such as `-1' from the set of allowed integer-literals?
|> >
|> >Simplicity. What is gained by specifying otherwise?
|>
|> Well, there are some problems due to the fact that 2's complement
|> representation has more negative numbers than positive numbers.
|> It is kind of ugly that you have to write `(-2147483647 - 1)'
|> rather than `-2147483648'.
But you couldn't write "-2147483648" in a portable program anyway; an
implementation is not required to have an integral type in which it is
representable. And you can already write it with most actual
implementations today, if (strict) portability is not an issue.
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: willhall@idt.net (Will Hall)
Date: 1997/03/13 Raw View
In article <01bc2fbf$98f0ace0$e56dadce@azguard>, "Bradd W. Szonye"
<Nutty_Irishman@msn.com> wrote:
>Well, maybe a programmer can't write "-2147483648" in a portable program,
>but the library implementers can use it to write "INT_MIN" or "LONG_MIN" if
>necessary.
As I noted in an earlier post, INT_MIN and LONG_MIN will not necessarily
be constant across implementations with, say, 32-bit and 64-bit int,
whereas `-2147483648' would be if it were portably representable on 32-bit
systems.
No, that is not to say that `-2147483648' will ever be portably
representable on implementations with 16-bit int, but so what? In a world
with a lot of 32-bit int impl's on the verge of having a lot of 64-bit
impl's, the ability to simply and portably represent the maximally
negative 32-bit int on either implementation is, IMHO, a good and easily
attainable feature for a language such as C++. (Also IMHO, "simply" could
be taken to mean "without having to resort to using an expression with one
unary and one binary operator".)
Note that in going from 64-bit to 128-bit implementations at some point
down the road, a similar issue will arise for the maximally negative
64-bit int.
-Will Hall
willhall@chelsea.ios.com
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: willhall@idt.net (Will Hall)
Date: 1997/03/13 Raw View
In article <rf5n2sasrc6.fsf@vx.cit.alcatel.fr>, James Kanze
<james-albert.kanze@vx.cit.alcatel.fr> wrote:
>willhall@idt.net (Will Hall) writes:
>|> [Q.2] What purpose is served by the exclusion of explicitly negative
>|> values such as `-1' from the set of allowed integer-literals?
>
>Simplicity. What is gained by specifying otherwise?
^^^^^^^^^^
^----------- [James Kanze cites "Simplicity" as purpose of excluding neg.s]
>
>--
>James Kanze
[ snip ... followed by excerpt from later post by James Kanze]
>willhall@idt.net (Will Hall) writes:
>|> (3) Now comes the fun part: we have an unsigned long int which we must use
>|> to intialize an int. Trusty 4.7[3] guides us in obtaining a result ... do
>|> what we like, it tells us, or (to quote) "the value is
>|> implementation-defined".
>
>On typical compilers, for typical 2's complement 32 bit machines, the
>results are exactly what is expected, even if they are arrived at by a
>round-about means.
>
>It is true that this is only "typical" behavior, and not guaranteed by
>the standard. But the standard doesn't guarantee that there is any type
>in which -2147483648 can be represented, so you can't use this constant
>in a portable program anyway, no matter how the lexer scans it.
>
>|> What could be simpler than that?
[ sarcastic answer to my own rhetorical question snipped ]
>What does simple have to do with it? We are talking about C++, aren't
^^^^^^
^-------- [James Kanze asks what "simple" has to do with it?]
>we?
Yes, we are talking about C++, and I heartily agree with your (latest)
(tongue-in-cheek? if so, pardon my humor-impairment) implicit assessment
of the status of negative integer literals in the draft standard of said
language: at present, it is not very simple.
-Will Hall
willhall@idt.net
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Marcelo Cantos <marcelo@mds.rmit.edu.au>
Date: 1997/03/13 Raw View
bparker@gil.com.au (Brian Parker) writes:
>
> Marcelo Cantos <marcelo@mds.rmit.edu.au> wrote:
>
> > a = -2;
> >while parsed as two tokens (- and 2) is a constant expression, and
> >hence will be evaluated at compile time. Consequently the resulting
> >program will be identical to the program that would have resulted from
> >a single token (the number -2).
>
> For 2 that's true, but of couse it does prevent one from specifying
> the minimum 2's complement value of a signed type directly so it's not
> completely transparent.
#define INT_MIN (-(INT_MAX)-1)
Sure, you can't specify it directly as a literal, but that's a bad
idea anyway since it makes the code non-portable. In fact, I would
speculate that the usual reason to want to specify the most negative
number is because of the fact that it is the most negative number (and
not because an application coincidentally requires that particular
`magic' number), so INT_MIN is the preferred representation in most
cases.
--
______________________________________________________________________
Marcelo Cantos, Research Assistant marcelo@mds.rmit.edu.au
Multimedia Database Systems Group, RMIT__/_ _ Tel 61-3-9282-2497
723 Swanston St, Carlton VIC 3053 Aus/ralia ><_> Fax 61-3-9282-2490
/
Acknowledgements: errors - me; wisdom - God; funding - RMIT
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: willhall@idt.net (Will Hall)
Date: 1997/03/14 Raw View
In article
<bgrahkzqr5.fsf@janus.i-have-a-misconfigured-system-so-shoot-me>, Marcelo
Cantos <marcelo@mds.rmit.edu.au> wrote:
> #define INT_MIN (-(INT_MAX)-1)
>
> Sure, you can't specify it directly as a literal, but that's a bad
> idea anyway since it makes the code non-portable.
Does this mean it's a bad idea to use C++ to write any code tailored to
take advantage of hardware with large ints, if in order to do so, one must
specify literals too large in magnitude to be portable _down_ the scale of
all conceivable implementations?
Is it the case that, if it can be demonstrated that there is _some_
conforming implementation to which an example will not port (e.g., one
tailored to a hardware architecture of bygone days -- say it has 16-bit
ints), then there is no reason to make the example portable between
members of what may be, practically speaking, a more _relevant_ subset of
all conceivable implementations? E.g., the subset implementing ints as
32-bit, 64-bit or 128-bit? (Or, if you like, choose "the subset
implementing ints as having at least 32 bits.")
> ... In fact, I would
> speculate that the usual reason to want to specify the most negative
> number is because of the fact that it is the most negative number (and
> not because an application coincidentally requires that particular
> `magic' number) ...
Such a "magic number" may prove quite important in applications which care
about being portable across both 32-bit and 64-bit implementations.
-Will Hall
willhall@idt.net
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/14 Raw View
willhall@idt.net (Will Hall) writes:
|> >What does simple have to do with it? We are talking about C++, aren't
|> ^^^^^^
|> ^-------- [James Kanze asks what "simple" has to do with it?]
|> >we?
|>
|> Yes, we are talking about C++, and I heartily agree with your (latest)
|> (tongue-in-cheek? if so, pardon my humor-impairment) implicit assessment
|> of the status of negative integer literals in the draft standard of said
|> language: at present, it is not very simple.
Yes, my comment was meant humorously. C++ may have many qualities, but
I don't think that anyone would rank simplicity among them.
With regards to the negative integer problem, however: for the user of
the language, the problem doesn't exist. You write the number in a
normal fashion, and if it fits, you get what you expect. For once, it
is simple. For the implementor, the way the literals are described in
the standard is the simplest way, and since the results of describing
the language this way are exactly the same as you would have if the '-'
were part of the literal, why not. (If someone could show me a case
where the results were different, I would say you have an argument.)
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Marcelo Cantos <marcelo@mds.rmit.edu.au>
Date: 1997/03/14 Raw View
willhall@idt.net (Will Hall) writes:
>
> In article <01bc2fbf$98f0ace0$e56dadce@azguard>, "Bradd W. Szonye"
> <Nutty_Irishman@msn.com> wrote:
>
> >Well, maybe a programmer can't write "-2147483648" in a portable program,
> >but the library implementers can use it to write "INT_MIN" or "LONG_MIN" if
> >necessary.
>
> As I noted in an earlier post, INT_MIN and LONG_MIN will not necessarily
> be constant across implementations with, say, 32-bit and 64-bit int,
> whereas `-2147483648' would be if it were portably representable on 32-bit
> systems.
Why not...
#define INT32_MIN (-2147483647-1)
In one of your header files! Now that isn't so hard is it? Good
programming practice would mandate this anyway, since it more clearly
states your intention, even if you *could* type it as a simple
literal.
Magic number are almost always bad.
> Note that in going from 64-bit to 128-bit implementations at some point
> down the road, a similar issue will arise for the maximally negative
> 64-bit int.
The reality is that when the programmer wants to type -2147483648, it
is usually because he wants the lowest possible integer value, in
which case, INT_MIN is the better choice.
--
______________________________________________________________________
Marcelo Cantos, Research Assistant __/_ marcelo@mds.rmit.edu.au
Multimedia Database Systems Group, RMIT / _ Tel 61-3-9282-2497
723 Swanston St, Carlton VIC 3053 Aus/ralia ><_> Fax 61-3-9282-2490
Acknowledgements: errors - me; wisdom - God; funding - RMIT
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Marcelo Cantos <marcelo@mds.rmit.edu.au>
Date: 1997/03/14 Raw View
willhall@idt.net (Will Hall) writes:
>
> In article
> <bgrahkzqr5.fsf@janus.i-have-a-misconfigured-system-so-shoot-me>, Marcelo
> Cantos <marcelo@mds.rmit.edu.au> wrote:
>
> > #define INT_MIN (-(INT_MAX)-1)
> >
> > Sure, you can't specify it directly as a literal, but that's a bad
> > idea anyway since it makes the code non-portable.
>
> Does this mean it's a bad idea to use C++ to write any code tailored to
> take advantage of hardware with large ints, if in order to do so, one must
> specify literals too large in magnitude to be portable _down_ the scale of
> all conceivable implementations?
Downard portability is not a design goal of high performance software.
> Is it the case that, if it can be demonstrated that there is _some_
> conforming implementation to which an example will not port (e.g., one
> tailored to a hardware architecture of bygone days -- say it has 16-bit
> ints), then there is no reason to make the example portable between
> members of what may be, practically speaking, a more _relevant_ subset of
> all conceivable implementations? E.g., the subset implementing ints as
> 32-bit, 64-bit or 128-bit? (Or, if you like, choose "the subset
> implementing ints as having at least 32 bits.")
The fact that an implementation is conforming does not imply that any
and all programs must be able to run on it, this would imply that all
types should be eight bits to cater for 70's CPU's. It is totally
inappropriate to mandate 16-bit ints to cater for the possibility that
your program might need to run on DOS in real mode!
The reality is that high performance software needs to use the optimum
data sizes for the given architecture, and this is one of the design
goals of C and C++. If this weren't the case people wouldn't bother
using them. If a platform doesn't support 32-bits then you probably
wouldn't want to compile a 32-bit dependent program on it anyway.
>
> > ... In fact, I would
> > speculate that the usual reason to want to specify the most negative
> > number is because of the fact that it is the most negative number (and
> > not because an application coincidentally requires that particular
> > `magic' number) ...
>
> Such a "magic number" may prove quite important in applications which care
> about being portable across both 32-bit and 64-bit implementations.
Then #define it! Magic numbers are BAD!
--
______________________________________________________________________
Marcelo Cantos, Research Assistant __/_ marcelo@mds.rmit.edu.au
Multimedia Database Systems Group, RMIT / _ Tel 61-3-9282-2497
723 Swanston St, Carlton VIC 3053 Aus/ralia ><_> Fax 61-3-9282-2490
Acknowledgements: errors - me; wisdom - God; funding - RMIT
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Abhishek Chauhan <Abhishek.Chauhan@eng.sun.com>
Date: 1997/03/15 Raw View
Marcelo Cantos wrote:
> The reality is that when the programmer wants to type -2147483648, it
> is usually because he wants the lowest possible integer value, in
> which case, INT_MIN is the better choice.
I can think of "realities" where INT_MIN crops up out of computations,
and where it matters how you write it.
Consider some program that _generates_ C code. Say something like
xbitmap. xbitmap saves bitmap images as C header files. The file
contains a C-statement that initializes an array with the bits of the
bitmap. This allows you to include the file into your GUI code and
have the bitmap compiled into your program.
If a simple xbitmap programmer were to write something like -
cout << bitmap.bits[i];
to write out the bitmap bits, it would be an error when the resulting
"header file" is included in a C program, if one of the bitmap bits
happened to be same as the INT_MIN! (because it would be written out
as -2147483648, which, pedantically speaking, is not INT_MIN)
Instead (s)he would have to rise to the occasion and write:
if (bitmap.bits[i] == INT_MIN)
cout << "INT_MIN";
else
cout << bitmap.bits[i];
or better(?) yet, using a recent "trick" by Dietmar Kuehl, create a
"C Code" locale with a facet to print INT_MIN as "INT_MIN"! and then:
locale ccloc(cout.getloc(), new IntMinExpert(cout.getloc()));
cout.imbue(ccloc);
...
cout << bitmap.bits[i]; // Yesss! now we're talking c++
Programmers writing tools/scripts to generate C/C++ code, in languages
other then C++ are out of luck. They would still have to check
whenever they output integers, to make sure they emit "INT_MIN" when
they mean -2147483648 or whatever.
BTW-0, negative integer literals are "inherited" from C, isn't it? So
can't we just delegate this issue to our base class -- The C Committee
:)
BTW-1, are there any languages that treat the "-" sign as part of the
literal and consequently "-1" as a single token?
-abhishek
---
Abhishek Chauhan, abhishek.chauhan@sun.com
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: willhall@idt.net (Will Hall)
Date: 1997/03/15 Raw View
In article
<bg67yubsuc.fsf@janus.i-have-a-misconfigured-system-so-shoot-me>, Marcelo
Cantos <marcelo@mds.rmit.edu.au> wrote:
> Why not...
>
> #define INT32_MIN (-2147483647-1)
>
> In one of your header files!
You're absolutely right -- AFAIK, this is currently the way to minimize
the number of times one has to use the -X-1 specification in a program.
> ... Now that isn't so hard is it?
It's not hard if the programmer in question is already aware of the
language quirk (shortcoming?) that necessitates such practice. How about
for the programmer who encounters this feature for the first time,
diiscovering it only after having _naively_ assumed that a 32-bit
implementation (which is not _required_ to have -2147483648 be what it
looks like) would support simple direct specification of all values of one
of its built-in types?
[Also, perhaps no one else takes this view, but wouldn't anyone out there
feel the slightest bit _embarrassed_ for a standard that _necessitated_
such a roundabout means of specifying a constant int value perfectly
representable by a given implementation?]
> ... Good
> programming practice would mandate this anyway, since it more clearly
> states your intention, even if you *could* type it as a simple
> literal.
To bring up good programming practice is to dilute the issue with what is,
frankly, a matter of opinion the standard does not presume to address.
> Magic number are almost always bad.
Oh. Ok. I guess one _does_ have to be careful with them in a language like
C++, where the standard doesn't guarantee their portable direct
specification on that subset of implementations where they are
representable.
> > Note that in going from 64-bit to 128-bit implementations at some point
> > down the road, a similar issue will arise for the maximally negative
> > 64-bit int.
>
> The reality is that when the programmer wants to type -2147483648, it
> is usually because he wants the lowest possible integer value, in
> which case, INT_MIN is the better choice.
Oh. Ok. I guess you've done more research on such uses and know more about
what programmers want it for than I. I guess, even in a world with a lot
of 64-bit-int implementations on the horizon, there won't be many
programmers who are concerned with having the number -2^31 be _guaranteed_
to mean the same thing on extant 32-bit-int systems as it does when they
specify it (more-or-less) directly as -2147483648 on a 64-bit-int
implementation. Ditto for -2^63 on 128-bit systems vs. 64-bit.
As an aside, I would like to note that, though this thread has been called
silly by some and its subject matter dismissed as a non-issue, the only
reasons given for such assessments have been: programming style
recommendations (or "mandates"), lexer-writer's fatigue, "the standard may
not require it but most implementations do it that way anyway", and
superstition about magic numbers.
All of this really begs the fundamental question: Why can't the set of all
integer literals (including all negatives) representable by a given
implementation also be directly specified in the C++ language? Ideally,
"directly" would mean "without resorting to grammar-level parsing (even
unary negation)," but at a minimum, it should mean "without resorting to
non-trivial expressions involving binary operations such as subtraction,
e.g., - 214783647 - 1".
-Will Hall
willhall@idt.net
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/11 Raw View
willhall@idt.net (Will Hall) writes:
|> [Q.1] It appears that there is no portable way to directly specify a value
|> of type int that is negative (where, by directly, I mean w/o using the
|> unary '-' op, and w/o performing any standard conversions) -- is this so?
|>
|> According to the 12/96 WP (you see -- technically, this is not off-topic
|> after all) an integer-literal has no explicit sign, so e.g., in `int i =
|> -1' the RHS is not an integer-literal, and presumably i is initialized (in
|> a strictly grammatical sense, ignoring implementation elision) by the
|> expression consisting of unary minus, followed by the integer-literal of
|> type int whose value is `1'. (Note that this assumes an implementation
|> wherein type int can represent values as large as `1'.)
This is the case with all languages I'm familiar with. In Fortran, for
example, the expression "i + -3" is (or was, at least) illegal, because
it was illegal to have two adjacent operators. "-3" was two tokens, the
operator "-", and the integer literal "3".
You speak of "implementation elision": in this case, the compile time
evaluation of the expression (a constant integral expression) is
required by the standard, so there is nothing "implementation" about it.
|> It strikes me as somehow distasteful that there are allowed values of a
|> type as fundamental as int which cannot be directly represented as
|> literals (specifically, as integer-literals). It is especially puzzling
|> that this is so (if indeed it is) in light of the fact that for floating
|> types (float, double), a floating-literal can be specified directly with a
|> sign (assuming the implementation can represent it), for example, `double
|> d = -1.0'.
The difference is subtle: there is NO requirement for compile time
evaluation of floating point values. In order for something like:
double d = -2.5 ;
(at file scope) to be a static initializaton, it is necessary that the
sequence "-2.5" be a literal.
(The distinction between static initialization and dynamic
initialization is, in turn, important for the order of initialization.
Consider:
extern double d1 ;
double d2 = d1 ; // dynamic initialization !!
double d1 = -2.5 ;
In this code fragment, the double d2 should be initialized to -2.5.
Change the initialization expression of d1 to "0.0 - 2.5", however, and
it should be initialized to 0. (I think. The implementation may be
allowed to "extend" what it can do as static initialization, in which
case, the initial value of d2 is implementation dependant, either 0.0 or
-2.5 would be legal.)
|> This brings me to the second question:
|>
|> [Q.2] What purpose is served by the exclusion of explicitly negative
|> values such as `-1' from the set of allowed integer-literals?
Simplicity. What is gained by specifying otherwise?
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: jpotter@falcon.lhup.edu (John E. Potter)
Date: 1997/03/12 Raw View
Marcelo Cantos (marcelo@mds.rmit.edu.au) wrote:
: willhall@idt.net (Will Hall) writes:
: > [Q.1] It appears that there is no portable way to directly specify a value
: > of type int that is negative (where, by directly, I mean w/o using the
: > unary '-' op, and w/o performing any standard conversions) -- is this so?
: >
: > It strikes me as somehow distasteful...
: > that this is so (if indeed it is) in light of the fact that for floating
: > types (float, double), a floating-literal can be specified directly with a
: > sign (assuming the implementation can represent it), for example, `double
: > d = -1.0'.
[ explaination for integeral types ]
: I am surprised that floating point literals would behave differently
: since the same problem would arise.
Don't be, it's wrong. From 2.13.3
floating-literal: fractional-const ... | digit-sequence ...
fractional-constant: digit-sequence ... | . ...
digit-sequence: digit ...
So no matter how you slice it, a floating-literal starts with either
a digit or a decimal point. There is no provision for a sign.
John
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: fjh@murlibobo.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/03/12 Raw View
James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:
>willhall@idt.net (Will Hall) writes:
>
>|> [Q.2] What purpose is served by the exclusion of explicitly negative
>|> values such as `-1' from the set of allowed integer-literals?
>
>Simplicity. What is gained by specifying otherwise?
Well, there are some problems due to the fact that 2's complement
representation has more negative numbers than positive numbers.
It is kind of ugly that you have to write `(-2147483647 - 1)'
rather than `-2147483648'.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/12 Raw View
Marcelo Cantos <marcelo@mds.rmit.edu.au> writes:
|> This is more of a lexical issue than a language design issue. Given
|> that lexical analysers are required to find the largest possible valid
|> token, the following snippet:
|>
|> 5-3
|>
|> would be parsed as two consecutive numbers (5 and -3), which is a
|> syntax error. In reality, the literal in the assignment:
|>
|> a = -2;
|>
|> while parsed as two tokens (- and 2) is a constant expression, and
|> hence will be evaluated at compile time. Consequently the resulting
|> program will be identical to the program that would have resulted from
|> a single token (the number -2).
|>
|> I am surprised that floating point literals would behave differently
|> since the same problem would arise.
They don't, at least not according to the draft. A floating point
literal must begin with either a "digit-sequence" or a ".".
Also, I was apparently mistaken in my previous posting: a C++ compiler
is required to handle floating point constant expressions, and not just
treat literals as compile time constants. (I have definite memories
that this was not the case in C, although I could be wrong. The obvious
reason why it wouldn't be required is that it requires a cross-compiler
to fully emulate the floating point arithmetic of the target machine,
including various idiosyncrecies in rounding, etc.)
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: bparker@gil.com.au (Brian Parker)
Date: 1997/03/12 Raw View
Marcelo Cantos <marcelo@mds.rmit.edu.au> wrote:
> a = -2;
>while parsed as two tokens (- and 2) is a constant expression, and
>hence will be evaluated at compile time. Consequently the resulting
>program will be identical to the program that would have resulted from
>a single token (the number -2).
For 2 that's true, but of couse it does prevent one from specifying
the minimum 2's complement value of a signed type directly so it's not
completely transparent.
,Brian Parker (bparker@gil.com.au)
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: willhall@idt.net (Will Hall)
Date: 1997/03/12 Raw View
As Bradd Szonye, John E. Potter and James Kanze each pointed out, there is
no provision for a sign in floating literals, so the lexical conventions
for integer literals and floating literals are parallel in this respect.
My apologies for carelessly implying otherwise in my initial post.
However, as to Kanze's characterization of the exclusion of negatives from
the set of allowed integer literals as resulting in "simplicity" (see
below), I would like to provide an interesting example (similar to one
posted by Fergus Henderson -- also see below -- but with a different emphasis):
int i = -2147483648; // -2^31 is the desired initializer
(1) Assuming for argument's sake that int and long are both 32-bit types,
the literal 2147483648 (colloquially, 2^31), too large to be an int, is
taken (2.13.1[2]) as an unsigned long int.
(2) As the literal quantity achieved in (1) is unsigned, unary `-'
(5.3[7]) subtracts it from 2^n, where n (the # of bits in the type of the
operand, unsigned long int) is 32 in this example, of the unsigned long
int in (1). The result is (mathematically) 2^32 - 2^31 = 2^31, and the
type of the result (still from 5.3[7]) is unsigned long int; so the net
effect of the unary negation is nil: it's a no-op for this particular
example.
(3) Now comes the fun part: we have an unsigned long int which we must use
to intialize an int. Trusty 4.7[3] guides us in obtaining a result ... do
what we like, it tells us, or (to quote) "the value is
implementation-defined".
What could be simpler than that?
(Hint: starts with "signed", ends with "integer literals".)
-Will Hall
(willhall@idt.net)
:James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:
:
:>willhall@idt.net (Will Hall) writes:
:>
:>|> [Q.2] What purpose is served by the exclusion of explicitly negative
:>|> values such as `-1' from the set of allowed integer-literals?
:>
:>Simplicity. What is gained by specifying otherwise?
:
:Well, there are some problems due to the fact that 2's complement
:representation has more negative numbers than positive numbers.
:It is kind of ugly that you have to write `(-2147483647 - 1)'
:rather than `-2147483648'.
:
:--
:Fergus Henderson <fjh@cs.mu.oz.au>
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Jason Merrill <jason@cygnus.com>
Date: 1997/03/12 Raw View
>>>>> Brian Parker <bparker@gil.com.au> writes:
> Marcelo Cantos <marcelo@mds.rmit.edu.au> wrote:
>> a = -2;
>> while parsed as two tokens (- and 2) is a constant expression, and
>> hence will be evaluated at compile time. Consequently the resulting
>> program will be identical to the program that would have resulted from
>> a single token (the number -2).
> For 2 that's true, but of couse it does prevent one from specifying
> the minimum 2's complement value of a signed type directly so it's not
> completely transparent.
Except that there *is* a simple way to specify that value:
INT_MIN
or
numeric_limits<int>::min()
Why on earth would you want to write -2147483648?
Jason
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: willhall@idt.net (Will Hall)
Date: 1997/03/12 Raw View
In article <u9endl54f3.fsf@yorick.cygnus.com>, Jason Merrill
<jason@cygnus.com> wrote:
>>>>>> Brian Parker <bparker@gil.com.au> writes:
>
>> Marcelo Cantos <marcelo@mds.rmit.edu.au> wrote:
>>> a = -2;
>>> while parsed as two tokens (- and 2) is a constant expression, and
>>> hence will be evaluated at compile time. Consequently the resulting
>>> program will be identical to the program that would have resulted from
>>> a single token (the number -2).
>
>> For 2 that's true, but of couse it does prevent one from specifying
>> the minimum 2's complement value of a signed type directly so it's not
>> completely transparent.
>
>Except that there *is* a simple way to specify that value:
>
> INT_MIN
>
>or
>
> numeric_limits<int>::min()
>
>Why on earth would you want to write -2147483648?
>
>Jason
Will INT_MIN be constant across systems with 32-bit int vs. 64-bit int, e.g.?
The number `-2147483648' would be -- if the standard did not release
implementations from the requirement of having it portably represent -2^31
on 32-bit systems.
Also, don't forget about about `-0x0100000000'. Personally, I would prefer
that to any of the following less transparent means of specifying the
value in question:
INT_MIN
-0x00ffffffff - 1
-2147483647 - 1
-Will Hall
willhall@idt.net
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/13 Raw View
willhall@idt.net (Will Hall) writes:
|> As Bradd Szonye, John E. Potter and James Kanze each pointed out, there is
|> no provision for a sign in floating literals, so the lexical conventions
|> for integer literals and floating literals are parallel in this respect.
|> My apologies for carelessly implying otherwise in my initial post.
|>
|> However, as to Kanze's characterization of the exclusion of negatives from
|> the set of allowed integer literals as resulting in "simplicity" (see
|> below), I would like to provide an interesting example (similar to one
|> posted by Fergus Henderson -- also see below -- but with a different
|> emphasis):
|> int i = -2147483648; // -2^31 is the desired initializer
|>
|> (1) Assuming for argument's sake that int and long are both 32-bit types,
|> the literal 2147483648 (colloquially, 2^31), too large to be an int, is
|> taken (2.13.1[2]) as an unsigned long int.
|>
|> (2) As the literal quantity achieved in (1) is unsigned, unary `-'
|> (5.3[7]) subtracts it from 2^n, where n (the # of bits in the type of the
|> operand, unsigned long int) is 32 in this example, of the unsigned long
|> int in (1). The result is (mathematically) 2^32 - 2^31 = 2^31, and the
|> type of the result (still from 5.3[7]) is unsigned long int; so the net
|> effect of the unary negation is nil: it's a no-op for this particular
|> example.
|>
|> (3) Now comes the fun part: we have an unsigned long int which we must use
|> to intialize an int. Trusty 4.7[3] guides us in obtaining a result ... do
|> what we like, it tells us, or (to quote) "the value is
|> implementation-defined".
On typical compilers, for typical 2's complement 32 bit machines, the
results are exactly what is expected, even if they are arrived at by a
round-about means.
It is true that this is only "typical" behavior, and not guaranteed by
the standard. But the standard doesn't guarantee that there is any type
in which -2147483648 can be represented, so you can't use this constant
in a portable program anyway, no matter how the lexer scans it.
|> What could be simpler than that?
What does simple have to do with it? We are talking about C++, aren't
we?
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: willhall@idt.net (Will Hall)
Date: 1997/03/10 Raw View
[Moderator's note: the poster's original subject line was "potentially
off-topic language quibble", but I took the liberty of substituting a
hopefully more informative subject line. -Moderator (fjh).]
This quibble takes the form of two questions:
[Q.1] It appears that there is no portable way to directly specify a value
of type int that is negative (where, by directly, I mean w/o using the
unary '-' op, and w/o performing any standard conversions) -- is this so?
According to the 12/96 WP (you see -- technically, this is not off-topic
after all) an integer-literal has no explicit sign, so e.g., in `int i =
-1' the RHS is not an integer-literal, and presumably i is initialized (in
a strictly grammatical sense, ignoring implementation elision) by the
expression consisting of unary minus, followed by the integer-literal of
type int whose value is `1'. (Note that this assumes an implementation
wherein type int can represent values as large as `1'.)
It strikes me as somehow distasteful that there are allowed values of a
type as fundamental as int which cannot be directly represented as
literals (specifically, as integer-literals). It is especially puzzling
that this is so (if indeed it is) in light of the fact that for floating
types (float, double), a floating-literal can be specified directly with a
sign (assuming the implementation can represent it), for example, `double
d = -1.0'.
This brings me to the second question:
[Q.2] What purpose is served by the exclusion of explicitly negative
values such as `-1' from the set of allowed integer-literals?
-Will Hall
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Marcelo Cantos <marcelo@mds.rmit.edu.au>
Date: 1997/03/11 Raw View
willhall@idt.net (Will Hall) writes:
> This quibble takes the form of two questions:
>
> [Q.1] It appears that there is no portable way to directly specify a value
> of type int that is negative (where, by directly, I mean w/o using the
> unary '-' op, and w/o performing any standard conversions) -- is this so?
>
> It strikes me as somehow distasteful...
> that this is so (if indeed it is) in light of the fact that for floating
> types (float, double), a floating-literal can be specified directly with a
> sign (assuming the implementation can represent it), for example, `double
> d = -1.0'.
This is more of a lexical issue than a language design issue. Given
that lexical analysers are required to find the largest possible valid
token, the following snippet:
5-3
would be parsed as two consecutive numbers (5 and -3), which is a
syntax error. In reality, the literal in the assignment:
a = -2;
while parsed as two tokens (- and 2) is a constant expression, and
hence will be evaluated at compile time. Consequently the resulting
program will be identical to the program that would have resulted from
a single token (the number -2).
I am surprised that floating point literals would behave differently
since the same problem would arise.
> [Q.2] What purpose is served by the exclusion of explicitly negative
> values such as `-1' from the set of allowed integer-literals?
Less work for the lexer.
--
______________________________________________________________________
Marcelo Cantos, Research Assistant marcelo@mds.rmit.edu.au
Multimedia Database Systems Group, RMIT__/_ _ Tel 61-3-9282-2497
723 Swanston St, Carlton VIC 3053 Aus/ralia ><_> Fax 61-3-9282-2490
/
Acknowledgements: errors - me; wisdom - God; funding - RMIT
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]