Sunday, June 14, 2015

Digest for comp.lang.c++@googlegroups.com - 13 updates in 4 topics

Richard Damon <Richard@Damon-Family.org>: Jun 13 08:40PM -0400

On 6/13/15 6:48 PM, Jens Thoms Toerring wrote:
> then, so it's ok since they don't realize that there are
> other processor architectures than what they're used to...
 
> Regards, Jens
 
Not quite. int must store as a minimum the range -32757 to 32767 (it
could be wider), while int16_t must have exactly the range -32768 to 32767.
 
using int16_t (or especially int8_t) says that you are going to support
your program on "normal" machines, it just won't compile on a machine
that isn't 2s complement, with normal word sizes. The exact types just
automatically limit you machine choice, the generic int type lets your
program compile on all machines, you just need to be careful to not make
unwarranted assumptions on the properties of the numbers.
 
If you want to avoid int, but not restrict what machines it can work on
would need to use int_least16_t or int_fast16_t instead of int (and deal
with exactly the same set of issues as you might have with int, as you
just know the minimum size for you numbers).
 
The biggest issue with using types like int16_t comes with using
*printf, as you KNOW the formats usable with int, but int16_t or int32_t
you don't so you need to use ugly preprocessor macros to build the
format specifiers. This is less of an issue with C++ than C as the idiom
is to use stream inserters (<<) which will "just work", but there may
still be some interfaces using the "C" format specifiers.
 
I guess the summary is that int16_t might make you code more "portable"
if you aren't careful in your coding. (The compiler will enforce your
assumptions). Using int might make your code more portable if you are
careful, or you could use int_least16_t/int_fast16_t if you want a bit
more control over your types. (more important for the 32 bit type, as if
you need 32 bits, the built in type to use would be long, but that might
be 64 bits, with int being 32 bit, so int_least32_t lets you more
precisely specify in a portable manner.)
David Brown <david.brown@hesbynett.no>: Jun 14 01:21PM +0200

On 14/06/15 01:29, Ben Bacarisse wrote:
 
>> Admittedly, Mr Flibble gets cross, but isn't that way of expressing it
>> a little pedantic, to say the least of it?
 
> How would you put it less pedantically?
 
By writing "range" instead of "rage" - Daniel was making a pun on your typo.
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Jun 14 06:36AM -0600

In modern C++ we should avoid using 'int' and its associates such as
'short' and 'long' as they are all non-portable and unsafe (their size
and value range can differ from one implementation to the next); instead
one should use the typedefs from <cstdint> instead.
 
A consequence of this rule is that we must never use 'auto' with integer
literals such as:
 
auto i = 42;
 
or
 
auto i = 42u;
 
instead we write:
 
int32_t i = 42;
 
or
 
uint32_t i = 42u;
 
The fact we have to do this is due to shortcoming of the current C++
Standard; what we need is something like:
 
auto i = 42s32; // signed, 32-bits
 
or
 
auto i = 42u32; // unsigned, 32-bits
 
/Flibble
 
 
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Ben Bacarisse <ben.usenet@bsb.me.uk>: Jun 14 12:51PM +0100

>>> a little pedantic, to say the least of it?
 
>> How would you put it less pedantically?
 
> By writing "range" instead of "rage" - Daniel was making a pun on your typo.
 
Ah. One of the problems with dyslexia is that such things are almost
invisible to me but I hope everyone else enjoyed the joke.
 
--
Ben.
David Brown <david.brown@hesbynett.no>: Jun 14 02:12PM +0200

On 14/06/15 13:51, Ben Bacarisse wrote:
 
>> By writing "range" instead of "rage" - Daniel was making a pun on your typo.
 
> Ah. One of the problems with dyslexia is that such things are almost
> invisible to me but I hope everyone else enjoyed the joke.
 
Spell chequers can't help with everything! (I too am mildly dyslexic -
my spelling is hopeless. It's easier to spot such typos in others posts
and in ones own posts.)
Rosario19 <Ros@invalid.invalid>: Jun 14 03:37PM +0200

On Sat, 13 Jun 2015 10:59:00 -0700 (PDT), gwowen wrote:
>> instead we write:
 
>> int32_t i = 42;
 
>Nothing says "portable" like using a type that is explicitly marked as "optional".
 
for me the prog use int, or unsigned or char or short or some pointers
can be portable only using the range values of each type the standard
guarantee
 
for me can be portable all programs using fixed size type
and fixed size pointers
 
for
char *a;
there is no possible portability
 
but for
uint32_t a;
see as pointer there is a workaroud for make "a" be a portable pointer
 
but, what is portability?
 
malloc(size)
in some machine, in some time, will return 0 in other return one good
ponter etc...
Melzzzzz <mel@zzzzz.com>: Jun 14 06:00PM -0600

On Sun, 14 Jun 2015 06:36:18 CST
 
> int32_t i = 42;
 
> or
 
> uint32_t i = 42u;
 
I would never use auto for simple initialization and when types are
obvious (like int), rather I would use auto to avoid long templates.
 
 
 
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Francis Glassborow <francis.glassborow@btinternet.com>: Jun 14 06:07PM -0600

On 14/06/2015 13:36, Mr Flibble wrote:
> 'short' and 'long' as they are all non-portable and unsafe (their size
> and value range can differ from one implementation to the next); instead
> one should use the typedefs from <cstdint> instead.
 
If it matters then your program is already dangerous and relying on
undefined behaviour. Note that unless your program results in
overflow/underflow there is no problem with signed types.
 
If your program is using unsigned types and is relying on the defined
behaviour for over/underflow then you already have an essentially
non-portable program because there is no requirement for exact sizes to
exist. It is perfectly OK for all unsigned int types to be 64-bit. I do
not know any system where this is the case but there are certainly
systems where unsigned char, unsigned short, unsigned int and unsigned
long are all 32-bit.
 
In almost all cases you should simply use the standard type that
guarantees sufficient range for your needs.
 
Finally, you can simply use long long and unsigned long long everywhere
and mark all literals as either LL or ULL.
 
I think the added complexity of using the <cstdint> typedefs routinely
whether needed or not is a recipe for error.
 
Francis
 
 
 
 
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
"James K. Lowden" <jklowden@speakeasy.net>: Jun 14 06:11PM -0600

On Sun, 14 Jun 2015 06:36:18 CST
> 'short' and 'long' as they are all non-portable and unsafe (their
> size and value range can differ from one implementation to the next);
> instead one should use the typedefs from <cstdint> instead.
 
I disagree with this assertion. Hardware evolves, and nonspecialized
variables evolve along with it.
 
It's not strictly correct that "int" and "long" are nonportable. It's
more correct to say their size is adapted by the compiler to the
machine. Except in the case of I/O, ISTM that's an advantage.
 
We have working code today written in the era of 16-bit machines, when
32-bit accesses required two memory reads and extra CPU cycles to
compute. We have even more code dating from the VAX era, including
every operating system in common use. The transition to 64-bit
hardware was made easier, I would argue, by *not* specifying variable
sizes in terms of bits. Indeed, the biggest change has been away from
bare "int" to semantic, opaque types like size_t and off_t.
 
I'm very glad we have <cstdint>. It makes simple something that used
to ugly and arcane, and it a pleasure to use for e.g. network
programming. It's a mistake to think it makes ordinary variables
obsolete. Size usually doesn't matter very much, and is relative, and
changes over time.
 
--jkl
 
 
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
James Kuyper <jameskuyper@verizon.net>: Jun 14 06:11PM -0600

On 06/14/2015 08:36 AM, Mr Flibble wrote:
 
> auto i = 42s32; // signed, 32-bits
 
> or
 
> auto i = 42u32; // unsigned, 32-bits
 
That's going a bit too far, in my opinion. First of all, whenever using
an interface, it's generally best to use the types specified for that
interface, even if they include 'int', 'short', or 'long'.
 
Secondly, if there's a traditional type name that's essentially
equivalent to one of the size-named types, I'll normally use the
traditional name instead, simply to save on my typing (though the
savings are bigger for the signed types). Types I consider essentially
equivalent are:
 
[u]int_least8_t [un]signed char
[u]int_least16_t [unsigned] short
[u]int_fast16_t [unsigned] int
[u]int_fast32_t [unsigned] long
 
Much of my code is targeted specifically at POSIX, which guarantees that
CHAR_BIT == 8, in which case I'm also willing to treat [un]signed char
as equivalent to [u]int8_t, but only if I've inserted the following
protection in the same translation unit:
 
#include <limits.h>
#if CHAR_BIT != 8
#error CHAR_BIT != 8

No comments: