Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Avoid 'int' and associates.

124 views
Skip to first unread message

Mr Flibble

unread,
Jun 13, 2015, 12:43:06 PM6/13/15
to
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

Bo Persson

unread,
Jun 13, 2015, 1:57:26 PM6/13/15
to
Why?

The type int is available on ALL systems, and guaranteed to be able to
hold the value 42. int32_t is not available on systems lacking a 32-bit
two's complement type. Thus slightly less portable.


Bo Persson

gwowen

unread,
Jun 13, 2015, 1:59:09 PM6/13/15
to
On Saturday, June 13, 2015 at 5:43:06 PM UTC+1, Mr Flibble wrote:
> In modern C++ we should avoid using 'int' and its associates such as
> 'short' and 'long' as they are all non-portable and unsafe
> ....
> instead we write:
>
> int32_t i = 42;
>

Nothing says "portable" like using a type that is explicitly marked as "optional".

Mr Flibble

unread,
Jun 13, 2015, 2:05:37 PM6/13/15
to
Portable does not mean "compilable on all known platforms"; portable
means that code runs *correctly* as-is on all platforms for which it
compiles.

/Flibble


Luca Risolia

unread,
Jun 13, 2015, 2:06:21 PM6/13/15
to
Il 13/06/2015 18:43, Mr Flibble ha scritto:
> auto i = 42;

> instead we write:
>
> int32_t i = 42;

Why must one reserve 32bits for 42, if it can be stored in an int which
is, say, 16bit long?

Mr Flibble

unread,
Jun 13, 2015, 2:06:42 PM6/13/15
to
Because the type of 42 is 'int' and 'int' is unsafe and must not be
used. See my other reply for why you misunderstand what we mean by
"portable".

/Flibble

Mr Flibble

unread,
Jun 13, 2015, 2:07:42 PM6/13/15
to
You can also use int16_t.

/Flibble


Luca Risolia

unread,
Jun 13, 2015, 2:10:26 PM6/13/15
to
Il 13/06/2015 20:07, Mr Flibble ha scritto:
> You can also use int16_t.

Exactly, I can also use whatever auto gives me.

Mr Flibble

unread,
Jun 13, 2015, 2:11:35 PM6/13/15
to
No as doing so is unsafe as I have shown in my other replies.

/Flibble


Ben Bacarisse

unread,
Jun 13, 2015, 2:21:53 PM6/13/15
to
Mr Flibble <flibbleREM...@i42.co.uk> writes:

> 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);

That's a overstatement. Where the minimum guaranteed rage is adequate,
using these types is neither non-portable nor unsafe. (They can, of
course, be *used* in unsafe and non-portable ways but it's hard to think
of type that can't be so abused.)

<snip>
> instead we write:
>
> int32_t i = 42;

In most cases int_least32_t is a better choice. It's mandatory, and
will be the same as int32_t where such a type exists.

<snip>
--
Ben.

gwowen

unread,
Jun 13, 2015, 2:22:44 PM6/13/15
to
Except when you can't.

Choose a type based on your problem domain. Trying to decide which types are acceptable without reference to the problem domain is utterly idiotic.

If you're indexing a list Presidents of the US, you can use int without any portability issues.

If you're counting US Govt Debt, you need to be more explicit about the range of the variable.

Immutable rules are for people who don't know what they're doing.

Mr Flibble

unread,
Jun 13, 2015, 2:27:28 PM6/13/15
to
On 13/06/2015 19:22, gwowen wrote:
> On Saturday, June 13, 2015 at 7:07:42 PM UTC+1, Mr Flibble wrote:
>> On 13/06/2015 19:06, Luca Risolia wrote:
>>> Il 13/06/2015 18:43, Mr Flibble ha scritto:
>>>> auto i = 42;
>>>
>>>> instead we write:
>>>>
>>>> int32_t i = 42;
>>>
>>> Why must one reserve 32bits for 42, if it can be stored in an int which
>>> is, say, 16bit long?
>>
>> You can also use int16_t.
>
> Except when you can't.
>
> Choose a type based on your problem domain. Trying to decide which types are acceptable without reference to the problem domain is utterly idiotic.

Using 'int' everywhere is you NOT choosing a type at all; it is just you
not thinking properly about your problem domain so by your own words you
are "idiotic".

>
> If you're indexing a list Presidents of the US, you can use int without any portability issues.

Wrong; for indexing you should use an unsigned type usually std::size_t
(or container::size_type).

>
> If you're counting US Govt Debt, you need to be more explicit about the range of the variable.
>
> Immutable rules are for people who don't know what they're doing.

The code you write must be really unsafe; I wouldn't trust it as far as
I could throw it if it was printed on a large rock that I couldn't throw
very far.

/Flibble

Luca Risolia

unread,
Jun 13, 2015, 3:01:37 PM6/13/15
to
Il 13/06/2015 18:43, Mr Flibble ha scritto:
> 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

you are talking about variable templates, aren't you?

template<typename T> T I = T(42); // definition
...
auto i = I<std::int32_t>; // use

Mr Flibble

unread,
Jun 13, 2015, 3:04:05 PM6/13/15
to
No I am not; whatever that is is fugly.

/Flibble


Luca Risolia

unread,
Jun 13, 2015, 3:19:06 PM6/13/15
to
Il 13/06/2015 21:04, Mr Flibble ha scritto:
>>> 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

>> you are talking about variable templates, aren't you?

> No I am not; whatever that is is fugly.

Then what you are saying does not make any sense.

Why should the language provide a way to write:

auto i = 42s32;

if you can already safely initialize i with:

std::int32_t i{42};

The compiler will produce a diagnostic on narrowing conversions.

Mr Flibble

unread,
Jun 13, 2015, 3:24:17 PM6/13/15
to
On 13/06/2015 20:18, Luca Risolia wrote:
> Il 13/06/2015 21:04, Mr Flibble ha scritto:
>>>> 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
>
>>> you are talking about variable templates, aren't you?
>
>> No I am not; whatever that is is fugly.
>
> Then what you are saying does not make any sense.
>
> Why should the language provide a way to write:
>
> auto i = 42s32;

The language already does provide a way in the form of UDLs. I am
proposing that the following UDLs be added to the C++ Standard Library:

s8, s16, s32, s64, u8, u16, u32, u64.

>
> if you can already safely initialize i with:
>
> std::int32_t i{42};
>
> The compiler will produce a diagnostic on narrowing conversions.

Yes the current situation of relying on compiler diagnostics or worse
relying on unsafe non-portable code is so much better. </sarcasm>

/Flibble

woodb...@gmail.com

unread,
Jun 13, 2015, 3:57:09 PM6/13/15
to
I want my software to compile and run on as many platforms as
possible.

If you see any portability problems here, please let me know.
I've tested it on PC-BSD, Linux and Windows and not found any
problems.

#include "platforms.hh"

#include "ErrorWords.hh"
#include "getaddrinfo_wrapper.hh"
#include "poll_wrapper.hh"
#include "ReceiveBufferStack.hh"
#include "SendBufferStack.hh"
#include <stdio.h>
#include <stdlib.h> // exit
#include "syslog_wrapper.hh"
#include "zz.front_messages_middle.hh"

using namespace ::cmw;

int main (int argc,char** argv)
{
try{
if(argc<3 || argc>5)
throw failure("Usage: direct account-number .req-file-path [node] [port]");

windows_start();
getaddrinfo_wrapper res(3==argc?"::1"/*"127.0.0.1"*/:argv[3]
,argc<5?"55555":argv[4],SOCK_DGRAM);
auto rp=res.get();
SendBufferStack<> sendbuf;
for(;rp!=nullptr;rp=rp->ai_next){
if((sendbuf.sock_=::socket(rp->ai_family,rp->ai_socktype,0))>0)break;
}
if(-1==sendbuf.sock_)throw failure("socket call(s) failed ")<<GetError();

::pollfd pfd{sendbuf.sock_,POLLIN,0};
int waitMillisecs=30000;
for(int j=0;j<2;++j,waitMillisecs*=2){
front_messages_middle::Marshal(sendbuf,marshalling_integer(argv[1])
,argv[2]);
sendbuf.Flush(rp->ai_addr,rp->ai_addrlen);
if(poll_wrapper(&pfd,1,waitMillisecs)>0){
ReceiveBufferStack<SameFormat> buf(pfd.fd);
if(!buf.GiveBool())throw failure("CMWA: ")<<buf.GiveCharStar();
::exit(EXIT_SUCCESS);
}
}
throw failure("No reply received. Is the middle tier (CMWA) running?");
}catch(::std::exception const& ex){
::printf("%s: %s\n",argv[0],ex.what());
#ifndef CMW_WINDOWS
::openlog(argv[0],LOG_NDELAY,LOG_USER);
#endif
syslog_wrapper(LOG_ERR,"%s",ex.what());
return EXIT_FAILURE;
}
}


Brian
Ebenezer Enterprises - So far G-d has helped us.
http://webEbenezer.net

Ian Collins

unread,
Jun 13, 2015, 4:20:41 PM6/13/15
to
Claimed but not shown.

--
Ian Collins

Mr Flibble

unread,
Jun 13, 2015, 4:24:01 PM6/13/15
to
"their size and value range can differ from one implementation to the next"

/Flibble


Ian Collins

unread,
Jun 13, 2015, 4:31:55 PM6/13/15
to
Mr Flibble wrote:
> On 13/06/2015 21:20, Ian Collins wrote:
>> Mr Flibble wrote:
>>> On 13/06/2015 19:10, Luca Risolia wrote:
>>>> Il 13/06/2015 20:07, Mr Flibble ha scritto:
>>>>> You can also use int16_t.
>>>>
>>>> Exactly, I can also use whatever auto gives me.
>>>
>>> No as doing so is unsafe as I have shown in my other replies.
>>
>> Claimed but not shown.
>
> "their size and value range can differ from one implementation to the next"

So how does that make "for( auto n = 0; n < 10; ++n ) {//stuff}" unsafe?

Even in the embedded world where I work, fixed sizes types are only used
to represent fixed size things.

--
Ian Collins

Mr Flibble

unread,
Jun 13, 2015, 5:06:05 PM6/13/15
to
On 13/06/2015 21:31, Ian Collins wrote:
> Mr Flibble wrote:
>> On 13/06/2015 21:20, Ian Collins wrote:
>>> Mr Flibble wrote:
>>>> On 13/06/2015 19:10, Luca Risolia wrote:
>>>>> Il 13/06/2015 20:07, Mr Flibble ha scritto:
>>>>>> You can also use int16_t.
>>>>>
>>>>> Exactly, I can also use whatever auto gives me.
>>>>
>>>> No as doing so is unsafe as I have shown in my other replies.
>>>
>>> Claimed but not shown.
>>
>> "their size and value range can differ from one implementation to the
>> next"
>
> So how does that make "for( auto n = 0; n < 10; ++n ) {//stuff}" unsafe?

Depends what "stuff" does with n doesn't it?

> Even in the embedded world where I work, fixed sizes types are only used
> to represent fixed size things.

Then you are doing it wrong; your code is unsafe and not portable.

/Flibble

Jens Thoms Toerring

unread,
Jun 13, 2015, 6:48:24 PM6/13/15
to
The upper limit of what can be stored in an 'int' may differ
on different implementations, but there's a lower limit. An
'int' must at least be able to store what an 'int16_t' can
store (and a long at least what an 'int32_t' does), so there
is nothing "unsafe" about them. And that's nothing new - it's
been that way since the very first C standard from 1989, thus
for more than a quarter of a century.

On the other hand, using 'int' tells the compiler to use
the fastest ("most natural") type for the architecture,
which not necessarily is an 'int16_t'. At least advacate
the 'int_leastXX_t' types that don't force the compiler
to use a certain, possibly slower type (which may not
even exist everywhere).

Assuming that an 'int' would be able to store more than what
a 16-bit value can is, unfortunately, a not too uncommon mis-
conception (as is assuming that sizeof(int) is 4). That's the
well known "everything's a VAX^WIntel processor" syndrome. But
telling people with that mind-set that an 'int' is "unsafe"
won't make them change their ways - it seems to work for
then, so it's ok since they don't realize that there are
other processor architectures than what they're used to...

Regards, Jens
--
\ Jens Thoms Toerring ___ j...@toerring.de
\__________________________ http://toerring.de

Daniel

unread,
Jun 13, 2015, 7:13:26 PM6/13/15
to
On Saturday, June 13, 2015 at 2:21:53 PM UTC-4, Ben Bacarisse wrote:
>
> Where the minimum guaranteed rage is adequate ...

Admittedly, Mr Flibble gets cross, but isn't that way of expressing it a little pedantic, to say the least of it?

Daniel

Ben Bacarisse

unread,
Jun 13, 2015, 7:29:28 PM6/13/15
to
How would you put it less pedantically?

--
Ben.

Richard Damon

unread,
Jun 13, 2015, 8:41:16 PM6/13/15
to
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

unread,
Jun 14, 2015, 7:21:28 AM6/14/15
to
By writing "range" instead of "rage" - Daniel was making a pun on your typo.

Mr Flibble

unread,
Jun 14, 2015, 7:40:11 AM6/14/15
to

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

unread,
Jun 14, 2015, 7:51:17 AM6/14/15
to
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

unread,
Jun 14, 2015, 8:12:42 AM6/14/15
to
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

unread,
Jun 14, 2015, 9:37:16 AM6/14/15
to
On Sat, 13 Jun 2015 10:59:00 -0700 (PDT), gwowen wrote:
>On Saturday, June 13, 2015 at 5:43:06 PM UTC+1, Mr Flibble wrote:
>> In modern C++ we should avoid using 'int' and its associates such as
>> 'short' and 'long' as they are all non-portable and unsafe
>> ....
>> 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

unread,
Jun 14, 2015, 7:10:11 PM6/14/15
to

On Sun, 14 Jun 2015 06:36:18 CST
Mr Flibble <flibbleREM...@i42.co.uk> wrote:

>
> 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;

I would never use auto for simple initialization and when types are
obvious (like int), rather I would use auto to avoid long templates.

Francis Glassborow

unread,
Jun 14, 2015, 7:10:13 PM6/14/15
to

On 14/06/2015 13:36, Mr Flibble wrote:
>
> 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.
>

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

James K. Lowden

unread,
Jun 14, 2015, 7:20:12 PM6/14/15
to

On Sun, 14 Jun 2015 06:36:18 CST
Mr Flibble <flibbleREM...@i42.co.uk> wrote:

> 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.

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

James Kuyper

unread,
Jun 14, 2015, 7:20:14 PM6/14/15
to

On 06/14/2015 08:36 AM, Mr Flibble wrote:
>
> 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

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
#endif
--
James Kuyper

Paavo Helde

unread,
Jun 14, 2015, 9:30:13 PM6/14/15
to

Mr Flibble <flibbleREM...@i42.co.uk> wrote in
news:cZOdnSRj9NsZweHI...@giganews.com:

>
> 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.

Sorry, int is extremely portable, every C and C++ implementation has it
and it is guaranteed to work in a pretty large range (the actual range
can be checked quite easily via std::numeric_limits, BTW).

Note that the actually needed range often depends on the application
domain requirements and the hardware capabilities, both of which are out
of the control of the programmer and can change in time. So, at the time
of writing the programmer often does not have sufficient knowledge to
select the "correct" fixed-size type. The only exception is when it is
known that the numbers are relatively small and the limits do not matter,
and this is exactly what the generic int type is meant for.

For example, it used to be that the number of pixels in a single medical
image (2D or 3D) fits in 32 bits, but this assumption is slowly starting
to break. So all those apps who have used e.g. std::uint32_t for the
pixel index type will probably need a potentially painful upgrade cycle
in the future.

Instead of relying on a fixed type, the program should define a typedef
for each different usage case of int, which can be upgraded more cleanly
and easily when the need arises. The typedef itself can be based on a
fixed-size type or then not, this is not so crucial any more.

This is not something new, there is a reason why STL contains several
such typedefs as e.g. std::string::size_type. Using fixed-size types
would not be possible here. Fixed-size types should be directly used only
in places where the type sizes are indeed fixed, e.g. when composing a
TIFF file IFD in memory or something like that.

Cheers
Paavo

Daniel

unread,
Jun 14, 2015, 10:01:19 PM6/14/15
to
On Sunday, June 14, 2015 at 7:21:28 AM UTC-4, David Brown wrote:
> On 14/06/15 01:29, Ben Bacarisse wrote:
> > Daniel writes:
> >
> >> On Saturday, June 13, 2015 at 2:21:53 PM UTC-4, Ben Bacarisse wrote:
> >>>
> >>> Where the minimum guaranteed rage is adequate ...
> >>
> >> 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.

Ben's follow up was actually pretty good, I was 90 percent certain that he had got my joke.

Daniel

Juha Nieminen

unread,
Jun 15, 2015, 5:01:03 AM6/15/15
to
Mr Flibble <flibbleREM...@i42.co.uk> wrote:
> 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.

"int" is traditionally the "natural" most efficient integer type of the
platform.

If you are going to use std::int32_t instead, then in some obscure
platforms that might not be the most efficient integral type.
(And "obscure" may not even mean "ancient". It could well be that
some (current or future) 64-bit system has efficient 64-bit ints
and inefficient 32-bit integrals.)

It's probably safer to use std::int_least32_t if you want to ensure
safety, and the fact that the integral might have more than 32 bits
is a non-issue.

std::int32_t ought to be used only if you need *exactly* 32 bits
(eg. because you are handling some binary format, or require this
for memory usage reasons.)

In practice 'int' is just fine. If your library/program requires
values that are outside the range of a 16-bit ingeter, and you want
to make 100% sure that your library won't break, add a static_assert
that ensures it has enough bits.

--- news://freenews.netfront.net/ - complaints: ne...@netfront.net ---

gwowen

unread,
Jun 15, 2015, 6:10:31 AM6/15/15
to
On Saturday, June 13, 2015 at 7:27:28 PM UTC+1, Mr Flibble wrote:

> > Choose a type based on your problem domain. Trying to decide which types are acceptable without reference to the problem domain is utterly idiotic.
>
> Using 'int' everywhere is you NOT choosing a type at all; it is just you
> not thinking properly about your problem domain so by your own words you
> are "idiotic".

Nice strawman. Who recommended using 'int' everywhere?

> The code you write must be really unsafe;

Nope.

gwowen

unread,
Jun 15, 2015, 6:11:57 AM6/15/15
to
On Saturday, June 13, 2015 at 9:24:01 PM UTC+1, Mr Flibble wrote:

> > Claimed but not shown.
>
> "their size and value range can differ from one implementation to the next"
>
> /Flibble

Wait, weren't you recommending size_t a minute ago?

But "their size and value range can differ from one implementation to the next" so size_t must, by this logic (and way I say logic, I am using the word quite wrongly) be unsafe.

Chris Vine

unread,
Jun 15, 2015, 6:42:41 AM6/15/15
to
On Sat, 13 Jun 2015 17:43:07 +0100
Mr Flibble <flibbleREM...@i42.co.uk> wrote:
[snip]
> 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

The correct form for this kind of initialization in current C++11/14
if you want auto/template type deduction is:

auto i = std::int32_t{42};

auto i = std::uint32_t{42};

which also has the benefit of avoiding implicit narrowing conversions.
It seems good enough to me and I cannot see the point of yet more
unnecessary C++ syntax.

In addition, if you want minimum sizes you would be better off in most
cases using std::int_least32_t and std::uint_least32_t, as others have
said.

Chris

David Brown

unread,
Jun 15, 2015, 8:20:16 AM6/15/15
to

On 15/06/15 04:24, Paavo Helde wrote:
> Mr Flibble <flibbleREM...@i42.co.uk> wrote in
> news:cZOdnSRj9NsZweHI...@giganews.com:
>
>>
>> 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.
>
> Sorry, int is extremely portable, every C and C++ implementation has it
> and it is guaranteed to work in a pretty large range (the actual range
> can be checked quite easily via std::numeric_limits, BTW).
>

This all comes down to what is meant by "portable". An integer type has
several characteristics, such as availability, minimum range, size, etc.
For some of these, "int" is highly portable - it is found on any C++
system, and is guaranteed a minimum range of -32767 to +32767. But
other characteristics, such as its actual size, lack portability.
"int32_t" (and friends) on the other hand do not exist on all systems -
but when they /do/ exist, they give you cross-target portability
guarantees on size and range that you cannot get with plain "int".

If you need some or all of the additional characteristics of int32_t,
then int32_t is the most portable way to get that. If you just want a
counter or index, with a range up to +/- 32767, then "int" is the most
portable choice.


We should use the most appropriate type for the task in hand (which
could well be "auto") - sometimes it is "int", sometimes it is "int32_t".

Personally, I have very little use of "short" or "long", however. Bar
consistency with existing code, I can't see any use of "(unsigned)
short" that would not be better suited with "(u)int16_t", nor any use of
"long" that would not be better with "int32_t" or "int64_t", according
to what you actually /need/. And I think "unsigned char" and "signed
char" are meaningless monstrosities - plain "char" is good for character
data, while "uint8_t" and "int8_t" are appropriate for data bytes and
small unsigned or signed numbers. (On platforms without 8-bit chars,
(u)int_least8_t is better than (un)signed char.)

Richard

unread,
Jun 15, 2015, 10:53:52 AM6/15/15
to
[Please do not mail me a copy of your followup]

gwowen <gwo...@gmail.com> spake the secret code
<594fa9cd-c5d2-4e93...@googlegroups.com> thusly:

>On Saturday, June 13, 2015 at 7:27:28 PM UTC+1, Mr Flibble wrote:
>
>> Using 'int' everywhere is you NOT choosing a type at all;

Nonsense. It is choosing a type: signed integer.

>> it is just you
>> not thinking properly about your problem domain so by your own words you
>> are "idiotic".
>
>Nice strawman. Who recommended using 'int' everywhere?

Stroustrup, actually. I'm pretty sure in "The C++ Programming
Language" he recommends only using the specifically sized integer types
when you are certain that it really *needs* to be that size. An
example would be a 2-byte signed integer quantity read from a binary
byte stream using std::istream::read.

When I've looked at code that is littered with int32_t all over the
place, I find it not only ugly but it violates the open/closed
principle for design. 99.9999% of the time the 32-bitness of the
integer was not essential or important for the code, they simply
adopted that simple minded notion that everything should explicitly
declare integers of specific sizes.

Yes, C/C++ has a language model that more closely maps to the
underlying machine, giving it a nice efficient mapping to instructions.
But that doesn't mean we should turn all our C/C++ source code into
thinly veiled assembly language with everything forced into WORD,
DWORD, and QWORD quantities. (The Windows API makes this mistake --
WORD is 16 bits regardless of the actual size of the machine word!)
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

Scott Lurndal

unread,
Jun 15, 2015, 10:58:17 AM6/15/15
to
Luca Risolia <luca.r...@linux-projects.org> writes:
>Il 13/06/2015 18:43, Mr Flibble ha scritto:
>> auto i = 42;
>
>> instead we write:
>>
>> int32_t i = 42;
>
>Why must one reserve 32bits for 42, if it can be stored in an int which
>is, say, 16bit long?
>

Because it doesn't have the const attribute?

Richard

unread,
Jun 15, 2015, 11:06:39 AM6/15/15
to
[Please do not mail me a copy of your followup]

sl...@pacbell.net spake the secret code
<3KBfx.88383$xK5....@fx08.iad> thusly:
Clearly it needs to be stored in uint6_t.

Mr Flibble

unread,
Jun 15, 2015, 12:14:37 PM6/15/15
to
Ah but std::size_t is a special case: it should only be used in the
context of allocations or where it is aliased by a container::size_type
when indexing for example. The guarantees we have for std::size_t
within the context of what it is supposed to be used for make it quite
safe. If you are using std::size_t in other contexts where its size or
value range matter then you are again writing unsafe code and are doing
it wrong (TM).

/Flibble


Mr Flibble

unread,
Jun 15, 2015, 12:26:46 PM6/15/15
to
On 13/06/2015 19:21, Ben Bacarisse wrote:
> Mr Flibble <flibbleREM...@i42.co.uk> writes:
>
>> 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);
>
> That's a overstatement. Where the minimum guaranteed rage is adequate,
> using these types is neither non-portable nor unsafe. (They can, of
> course, be *used* in unsafe and non-portable ways but it's hard to think
> of type that can't be so abused.)

It isn't an overstatement at all. If using 'int', 'short' and 'long' is
unsafe in safety critical domains then it is also unsafe in *any* domain
(even if the worst that can happen is losing a life in a video game).
To quote the MISRA C++ coding standard:

"typedefs that indicate size and signedness should be used in place of
the basic numerical types."

/Flibble

Francis Glassborow

unread,
Jun 15, 2015, 12:30:12 PM6/15/15
to
So both C and C++ provide an integer type that is guaranteed to be at
least 32-bits, so why would I not use that when I need a 32-bit integer?
That is why int32_t better? Note that on systems with 32-bit int, long
int is usually also 32 bits.

And where I need 64 bits the (ugly) long long int meets my need.

If I use real types I do not have to worry about places where the
behaviour varies according to the underlying type (most commonly i/o in C)


I agree that short is pretty useless these days. It would have made more
sense if it had been an exact 16-bit integer type.

Francis

Lynn McGuire

unread,
Jun 15, 2015, 12:54:47 PM6/15/15
to
On 6/13/2015 11:43 AM, Mr Flibble wrote:
> 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

Int has always been signed and had four sizes for me over the years: 36 bits, 60 bits, 32 bits and 16 bits.

Lynn

Mr Flibble

unread,
Jun 15, 2015, 1:11:11 PM6/15/15
to
'int' is only guaranteed to be at least 16 bits but the actual problem
is the *at least* part: it can mean *different* sizes and value ranges
on *different* implementations resulting in *different* or even
*dangerous behaviour*. If you want a type that behaves like 'int' then
you should be explicit about it in your code by using 'int_fast16_t' but
absolute care must be taken when using such variable types.

>
> And where I need 64 bits the (ugly) long long int meets my need.
>
> If I use real types I do not have to worry about places where the
> behaviour varies according to the underlying type (most commonly i/o in C)

You should be writing code such that the underlying type doesn't
actually matter; that is part of the rationale for <cstdint> in the
first place.

/Flibble

woodb...@gmail.com

unread,
Jun 15, 2015, 1:50:54 PM6/15/15
to
In some cases I would use long or int_fast32_t rather than int,
but the system calls I'm using specify int in their interface.

int poll(struct pollfd fds[], nfds_t nfds, int timeout);

So there's not much I can do about it at this time.

Brian
Ebenezer Enterprises - Smile. G-d loves you and so do I.
http://webEbenezer.net

Mr Flibble

unread,
Jun 15, 2015, 2:10:11 PM6/15/15
to

On 15/06/2015 18:22, Francis Glassborow wrote:
>
'int' is only guaranteed to be at least 16 bits but the actual problem
is the *at least* part: it can mean *different* sizes and value ranges
on *different* implementations resulting in *different* or even
*dangerous behaviour*. If you want a type that behaves like 'int' then
you should be explicit about it in your code by using 'int_fast16_t' but
absolute care must be taken when using such variable types.

>
> And where I need 64 bits the (ugly) long long int meets my need.
>
> If I use real types I do not have to worry about places where the
> behaviour varies according to the underlying type (most commonly i/o in C)

You should be writing code such that the underlying type doesn't
actually matter; that is part of the rationale for <cstdint> in the
first place.

/Flibble


Richard

unread,
Jun 15, 2015, 2:33:37 PM6/15/15
to
[Please do not mail me a copy of your followup]

Lynn McGuire <l...@winsim.com> spake the secret code
<mlmvtt$8oi$1...@dont-email.me> thusly:

>Int has always been signed and had four sizes for me over the years: 36
>bits,

DECsystem-10/20?

>60 bits,

CDC Cyber?

>32 bits and 16 bits.

Well, these could be almost anything from x86 to PDP-11 to VAX to
embedded MIPS RISC CPU.

Lynn McGuire

unread,
Jun 15, 2015, 2:46:09 PM6/15/15
to
On 6/15/2015 1:33 PM, Richard wrote:
> [Please do not mail me a copy of your followup]
>
> Lynn McGuire <l...@winsim.com> spake the secret code
> <mlmvtt$8oi$1...@dont-email.me> thusly:
>
>> Int has always been signed and had four sizes for me over the years: 36
>> bits,
>
> DECsystem-10/20?
>
>> 60 bits,
>
> CDC Cyber?
>
>> 32 bits and 16 bits.
>
> Well, these could be almost anything from x86 to PDP-11 to VAX to
> embedded MIPS RISC CPU.

The UNIVAC 1108 was a 36 bit word, 6 byte word machine.

Lynn

Richard

unread,
Jun 15, 2015, 2:51:48 PM6/15/15
to
[Please do not mail me a copy of your followup]

Lynn McGuire <l...@winsim.com> spake the secret code
<mln6ep$5m0$1...@dont-email.me> thusly:
Ah.

Did I guess the 60-bit machine right?

Scott Lurndal

unread,
Jun 15, 2015, 3:43:34 PM6/15/15
to
legaliz...@mail.xmission.com (Richard) writes:
>[Please do not mail me a copy of your followup]
>
>Lynn McGuire <l...@winsim.com> spake the secret code
><mlmvtt$8oi$1...@dont-email.me> thusly:
>
>>Int has always been signed and had four sizes for me over the years: 36
>>bits,
>
>DECsystem-10/20?

Or Burroughs Large Systems. Or Univac 1100/2200.

Lynn McGuire

unread,
Jun 15, 2015, 3:53:00 PM6/15/15
to
On 6/15/2015 1:51 PM, Richard wrote:
> [Please do not mail me a copy of your followup]
>
> Lynn McGuire <l...@winsim.com> spake the secret code
> <mln6ep$5m0$1...@dont-email.me> thusly:
>
>> On 6/15/2015 1:33 PM, Richard wrote:
>>> [Please do not mail me a copy of your followup]
>>>
>>> Lynn McGuire <l...@winsim.com> spake the secret code
>>> <mlmvtt$8oi$1...@dont-email.me> thusly:
>>>
>>>> Int has always been signed and had four sizes for me over the years: 36
>>>> bits,
>>>
>>> DECsystem-10/20?
>>>
>>>> 60 bits,
>>>
>>> CDC Cyber?
>>>
>>>> 32 bits and 16 bits.
>>>
>>> Well, these could be almost anything from x86 to PDP-11 to VAX to
>>> embedded MIPS RISC CPU.
>>
>> The UNIVAC 1108 was a 36 bit word, 6 byte word machine.
>
> Ah.
>
> Did I guess the 60-bit machine right?

Yes. Model 7600. Another 6 bit machine with TEN bytes per word.

Lynn

Francis Glassborow

unread,
Jun 15, 2015, 4:00:11 PM6/15/15
to
If my code becomes dangerous I am already in undefined behaviour land
and that effectively means that I am relying on some behaviour that
breaks if int has more than 16-bits. Please give an example of code
which works for a 16-bit int but is broken for an int with more bits.


>
>>
>> And where I need 64 bits the (ugly) long long int meets my need.
>>
>> If I use real types I do not have to worry about places where the
>> behaviour varies according to the underlying type (most commonly i/o
>> in C)
>
> You should be writing code such that the underlying type doesn't
> actually matter; that is part of the rationale for <cstdint> in the
> first place.

Not really, the idea was to allow systems that had more types available
over and above those required by the standard to allow programmers to
express their needs. And the rationale was a purely C one and I doubt
that it would be in C++ other than for compatibility reasons.

For example it is possible that on a particular platform a 32-bit
integer type performs faster than a 16-bit one. However that has a smell
of premature optimisation.

In reality very few if any programmers have ever made use of those
extended types, and where they have, they are often not portable (there
is no guarantee that any of the exact types exist on a platform)

Anyway you are free to use anything you want even if most of us would
not do so and would often ask for change in a code review. Typedefs are
a potential source of problems, particularly in C++ where overloading
can be changed by a change in an underlying type.

Scott Lurndal

unread,
Jun 15, 2015, 4:56:37 PM6/15/15
to
Currently known as Unisys Clearpath Libra (Burroughs) and
Clearpath Dorado (Univac).

Scott Lurndal

unread,
Jun 15, 2015, 4:58:25 PM6/15/15
to
Burroughs medium systems. from 1/2 to 50 bytes per word.

(Variable length BCD operations up to 100 units in length, units
in either nibbles or bytes (where the zone digit is ignored)).

Not a natural system for C or C++.

Mr Flibble

unread,
Jun 15, 2015, 5:00:12 PM6/15/15
to
Can you back that assertion up with any facts at all?

>
> Anyway you are free to use anything you want even if most of us would
> not do so and would often ask for change in a code review. Typedefs are
> a potential source of problems, particularly in C++ where overloading
> can be changed by a change in an underlying type.

You are speaking for a lot of people there. As far as code reviews are
concerned the MISRA C++ coding standard for safey critical systems
prohibits the use of basic numerical types and mandates the use of the
typedefs from <cstdint> (or an equivalent).

You should be coding to an interface; if the interface is legacy and
takes an 'int' then you should of course perform a safe type conversion
to an 'int' however any new interfaces that are within your remit to
define should be using the typedefs from <cstdint> to ensure
cross-platform portability and correct program operation.

/Flibble

James Kuyper

unread,
Jun 15, 2015, 5:00:14 PM6/15/15
to

On 06/15/2015 03:02 PM, Mr Flibble wrote:
>
> On 15/06/2015 18:22, Francis Glassborow wrote:
...
> 'int' is only guaranteed to be at least 16 bits but the actual problem
> is the *at least* part: it can mean *different* sizes and value ranges
> on *different* implementations resulting in *different* or even
> *dangerous behaviour*. If you want a type that behaves like 'int' then

And how is that different from int_fast16_t?

> you should be explicit about it in your code by using 'int_fast16_t' but
> absolute care must be taken when using such variable types.

Please show code which uses 'int' when you think it should be using
'int_fast16_t', and explain the circumstances under which such code is
dangerous.

...
>> If I use real types I do not have to worry about places where the
>> behaviour varies according to the underlying type (most commonly i/o in C)
>
> You should be writing code such that the underlying type doesn't
> actually matter; that is part of the rationale for <cstdint> in the
> first place.

It is quite feasible to write code using short int, int, and long int,
where the underlying type doesn't actually matter. I have no objections
to <cstdint>, and would in fact have preferred it if C/C++ had adopted
types with such definitions from the very beginning, rather than adding
them on later. However, you exaggerate the problem when you claim that
that the older type names should never be used.
--
James Kuyper

Robert Wessel

unread,
Jun 15, 2015, 5:02:23 PM6/15/15
to
On Mon, 15 Jun 2015 14:52:41 -0500, Lynn McGuire <l...@winsim.com>
wrote:
Unless you were using it to store six 10-bit characters per word.

James Kuyper

unread,
Jun 15, 2015, 10:10:10 PM6/15/15
to

On 06/15/2015 05:54 PM, Mr Flibble wrote:
>
> On 15/06/2015 21:54, Francis Glassborow wrote:
...
>> In reality very few if any programmers have ever made use of those
>> extended types, and where they have, they are often not portable (there
>> is no guarantee that any of the exact types exist on a platform)
>
> Can you back that assertion up with any facts at all?

Which assertion are you referring to? Normally, "that" refers to the
most recently mentioned thing that it could refer to, but his very last
assertion is easy to back up: 7.20.1.1, describing the Exact-width
Types, says in paragraph 3: "These types are optional". His earlier
assertions are much more questionable, but if you meant to refer to one
of them, you should have used some phrase other than "that assertion".

...
> concerned the MISRA C++ coding standard for safey critical systems
> prohibits the use of basic numerical types and mandates the use of the
> typedefs from <cstdint> (or an equivalent).

I'm not impressed by MISRA's guidelines in general, and this one fits
into that pattern. I've only heard of them second-hand; a copy of those
guidelines is too expensive to justify buying one if you don't have an
obligation to follow those guidelines. However, what I've heard from
other people about those guidelines has not impressed me (and most of
those people were MISRA supporters).
--
James Kuyper

James Kuyper

unread,
Jun 15, 2015, 10:10:15 PM6/15/15
to

On 06/15/2015 04:54 PM, Francis Glassborow wrote:
...
> Not really, the idea was to allow systems that had more types available
> over and above those required by the standard to allow programmers to
> express their needs. And the rationale was a purely C one and I doubt
> that it would be in C++ other than for compatibility reasons.

I don't see that. What features of the rationale for the size-named
types are C specific? I see the desire to minimize either memory use or
processing time (and to have some control over which one is minimized)
as being pretty much universal, and especially so in lower-level
languages like C and C++.

> For example it is possible that on a particular platform a 32-bit
> integer type performs faster than a 16-bit one. However that has a smell
> of premature optimisation.

I don't see how it could be. If that's premature, when is "maturity" to
be achieved? That is, when should the decision be made to choose a type
based upon it's speed rather than it's size (or vice versa)?

> In reality very few if any programmers have ever made use of those
> extended types, and where they have, they are often not portable (there
> is no guarantee that any of the exact types exist on a platform)

I am mainly interested in the least- and fast-sized types, which are
guaranteed, so that's not a problem for me. And, in the rare
circumstance where I'd want to use an exact-sized type, the fact that I
decided to use it would imply, correctly, that the program would be
completely irrelevant to any platform which didn't support that type:
for instance, to implement the interface to hardware that, if attached
to a given system, necessarily implies that the exact-sized type must be
supported.

Note: I expect many people to use exact-sized types inappropriately,
under circumstances were that wouldn't be true - but it's not something
I would do.
--
James Kuyper

David Brown

unread,
Jun 16, 2015, 4:11:06 AM6/16/15
to
I agree with the fundamental principle that "general" C and C++
programming could benefit from following some of the same sort of coding
standards and guidelines as are used in embedded development. However...

There is a big difference between the quality and safety required for
different domains. It is acceptable that that a video game has
glitches, and even the risk of the occasional crash - it's a different
matter for a aircraft flight control system or an artificial respirator.
On the other hand, top-of-the-range quality controlled software
development has code productivity rates of a few lines of code per week
per developer - that is not going to be suitable for mainstream development.

There are also big differences in the sorts of coding rules that suit
small-system embedded development, and big system programming. In the
types of systems MISRA is targeted at, dynamic memory allocation is
often banned (for very good reasons) - imagine trying to program
"minesweeper" for Windows without "new", "malloc", or any OS calls that
used dynamic memory.

And as coding standards go, I've never been overly impressed with MISRA.
A lot of the rules are obvious and even superfluous, such as spelling
out (and banning) different sorts of ways to write code that is hard to
read, or banning undefined behaviour, or banning overlapping and mixing
try/catch blocks with switches and gotos. And some rules are downright
/wrong/, such as insisting on writing "if (1 == x)" as a way of
protecting against "if (x = 1)" mistakes - instead, you should get a
decent compiler or linter, and learn how to use the warnings.

There are many rules from embedded coding standards that would be good
in "big system" programming - but it would be even better to develop and
follow appropriate rules for the domain you are working in.

And as for this specific case, there is a lot more need of size-specific
types in embedded systems than in general C or C++ programming - while I
think many general C and C++ programmers should use them more, using
them everywhere is unnecessary even in embedded programming.


David Brown

unread,
Jun 16, 2015, 8:10:12 AM6/16/15
to
There are a few reasons to prefer int32_t to long. One is that when you
need 32 bits, it is no bigger than necessary - long is 64-bit on many of
the most common systems these days (such as most 64-bit *nix systems -
in particular, 64-bit Linux and BSD on x86-64).

Another is that it says exactly what you mean - it is absolutely clear
in the code that you picked that type because you wanted 32 bits. You
didn't just use a "long" because you thought the data might be a bit
big, or because you guessed a particular size for "long", or because
your code has ancestry back to 16-bit Windows and used "long" to hold
pointers.


>
> And where I need 64 bits the (ugly) long long int meets my need.

Yes, but "long long int" is /ugly/ ! And again, int64_t says exactly
what you mean.

David Brown

unread,
Jun 16, 2015, 8:10:19 AM6/16/15
to
MISRA standards are only £10 or £15 for the pdfs - it's not /that/
expensive! (But of course any cost makes the whole process a lot more
inconvenient, especially if you just want a quick look for curiosity.)


--

Scott Lurndal

unread,
Jun 16, 2015, 11:00:11 AM6/16/15
to

Mr Flibble <flibbleREM...@i42.co.uk> writes:
>
>On 15/06/2015 21:54, Francis Glassborow wrote:

>> For example it is possible that on a particular platform a 32-bit
>> integer type performs faster than a 16-bit one. However that has a smell
>> of premature optimisation.
>>
>> In reality very few if any programmers have ever made use of those
>> extended types, and where they have, they are often not portable (there
>> is no guarantee that any of the exact types exist on a platform)
>
>Can you back that assertion up with any facts at all?

Probably not. Most of the C++ code that I've worked on over the
last 20+ years uses these types (before they were standardized,
and with names like u32, uint32, uint32_t etc).

Granted most of that code ran sans OS (it was the OS), and required
fixed types to map to various hardware registers.

However, absent API requirements for other types, I would prefer
using types for which I understand the characteristics in all
conditions, thus I prefer the explicitly sized types. Having
run into many issues in the past porting software from 16-bit
ints to 32-bit ints (and from 32-bit longs to 64-bit longs),
I would never advocating using 'int' for anything.

Richard

unread,
Jun 16, 2015, 4:00:11 PM6/16/15
to

[Please do not mail me a copy of your followup]

sl...@pacbell.net spake the secret code
<utVfx.149824$Lj1....@fx07.iad> thusly:

>Granted most of that code ran sans OS (it was the OS), and required
>fixed types to map to various hardware registers.

This is the situation where I think the size of the data really *does*
matter and it's important to use sized types and not the implicit size
of int, long, etc. Things like structures representing byte streams
passed across the network (and you might do network-to-host byte
reordering in place on that structure), raw byte streams read from or
written to files, raw bytes transmitted between processes through
shared memory segments and so-on.

I've got some code im my open source project that doesn't use
specifically sized types for some binary file I/O and it's a mess right
because they used generic types. So I am certainly sympathetic to
cases where it matters.

My assertion is that it simply doesn't matter in *every* case.

>However, absent API requirements for other types, I would prefer
>using types for which I understand the characteristics in all
>conditions, thus I prefer the explicitly sized types. Having
>run into many issues in the past porting software from 16-bit
>ints to 32-bit ints (and from 32-bit longs to 64-bit longs),
>I would never advocating using 'int' for anything.

Here, I disagree. The size of every int in a program isn't a
portability concern. What's important is deciding which variables need
specific sizes and which don't.[*]

I've seen code where the compiler's default size of an int was 16-bits
and everywhere they wanted to iterate over containers or whatnot it was
int16_t all over the place. Then you move to a compiler where the
defaault size of an int is 32-bits. The fact that all those ints were
marked as 16-bits is now erroneous and simply a distraction. How do
you know which ones really needed to be 16-bits and which were 16-bits
simply because that was the default size of an int? Forcing them all
into a 16-bit straight jacket impedes portability instead of enhancing
it.

In other words, like most things in programming, it's a matter of good
judgment. Simplistically applying a rule like "never use int" is
opening up your skull and dumping your brains in the garbage. There is
a time when specifically sized types are important.

For most of the C++ I have worked on in the past 25 years, it was
important in only a very few cases. Working on code where the team
insisted on sizing every single named quantity in the application was
tedious and yielded little to no value. I have done very little
programming in embedded environments with strict resource limits and I
can see how someone who spent 25 years in that environment would
consider it indispensible that everything be specifically sized. So it
varies with experience and problem domain.

But this is just another reason to advocate for proper application of
good judgment for your problem domain instead of adopting a simplistic
rule. Even within a problem domain, things can change over time.
Embedded processors today have access to many more resources than they
did in the 80s when 64 users time shared out of 128KB of main memory
and an embedded CPU was lucky to have 128 bytes of RAM and 16K of ROM.

[*] Aside: if sizing is all that important, does that mean you encode
the byte size of a struct into its name? I mean, if it's really that
important for int to be declared to be a specific size, but you don't
similarly mandate the same thing for structs and classes, then this
is an academic exercise in pedantry.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>


James Kuyper

unread,
Jun 16, 2015, 4:00:13 PM6/16/15
to

On 06/16/2015 09:05 AM, David Brown wrote:
...
>> I'm not impressed by MISRA's guidelines in general, and this one fits
>> into that pattern. I've only heard of them second-hand; a copy of those
>> guidelines is too expensive to justify buying one if you don't have an
>> obligation to follow those guidelines. However, what I've heard from
>> other people about those guidelines has not impressed me (and most of
>> those people were MISRA supporters).
>>
>
> MISRA standards are only £10 or £15 for the pdfs - it's not /that/
> expensive! (But of course any cost makes the whole process a lot more
> inconvenient, especially if you just want a quick look for curiosity.)

IIRC, the last time I looked it was several hundred US$. A year ago, I
would have thought that £10 it would be almost worth paying for, just
out of curiosity. However, since the twins arrived I'm paying closer
attention to my money.

Chris M. Thomasson

unread,
Jun 16, 2015, 4:10:11 PM6/16/15
to

>"Mr Flibble" wrote in message
>news:y6OdnUG8htn2rOLI...@giganews.com...

> [...]
> You are speaking for a lot of people there. As far as code reviews are
> concerned the MISRA C++ coding standard for safey critical systems
> prohibits the use of basic numerical types and mandates the use of the
> typedefs from <cstdint> (or an equivalent).

Programming a warplane, anyone?:

http://www.stroustrup.com/JSF-AV-rules.pdf

;^)

Mr Flibble

unread,
Jun 16, 2015, 5:50:11 PM6/16/15
to
This is why you should design things properly perhaps by the use of a
traits class specialized for different hardware which has its own public
typedefs:

template <typename HardwareType>
struct foo_traits;

template <>
struct foo_traits<ZXSpectrum48K>
{
typedef uint16_t index_type;
};

typedef foo_traits<ZXSpectrum48K>::index_type index_type;

/* use index_type rather than uint16_t directly. */

/Flibble


--

David Brown

unread,
Jun 16, 2015, 5:50:13 PM6/16/15
to

On 16/06/15 22:59, James Kuyper wrote:
>
> On 06/16/2015 09:05 AM, David Brown wrote:
> ...
>>> I'm not impressed by MISRA's guidelines in general, and this one fits
>>> into that pattern. I've only heard of them second-hand; a copy of those
>>> guidelines is too expensive to justify buying one if you don't have an
>>> obligation to follow those guidelines. However, what I've heard from
>>> other people about those guidelines has not impressed me (and most of
>>> those people were MISRA supporters).
>>>
>>
>> MISRA standards are only £10 or £15 for the pdfs - it's not /that/
>> expensive! (But of course any cost makes the whole process a lot more
>> inconvenient, especially if you just want a quick look for curiosity.)
>
> IIRC, the last time I looked it was several hundred US$. A year ago, I
> would have thought that £10 it would be almost worth paying for, just
> out of curiosity. However, since the twins arrived I'm paying closer
> attention to my money.
>

That must have been a /long/ time ago - or perhaps you are mixing it
with some other standards (such as the current C++ standard, which is an
absurd $265).

If you have anything specific you want to ask about MISRA, let me know
and I can look it up - I can't send you a copy (since it would be
copyright infringement, and the pdf is watermarked with my name).

Mr Flibble

unread,
Jun 16, 2015, 5:50:17 PM6/16/15
to

On 16/06/2015 22:03, Chris M. Thomasson wrote:
>
>> "Mr Flibble" wrote in message
>> news:y6OdnUG8htn2rOLI...@giganews.com...
>
>> [...]
>> You are speaking for a lot of people there. As far as code reviews are
>> concerned the MISRA C++ coding standard for safey critical systems
>> prohibits the use of basic numerical types and mandates the use of the
>> typedefs from <cstdint> (or an equivalent).
>
> Programming a warplane, anyone?:
>
> http://www.stroustrup.com/JSF-AV-rules.pdf

From that document (relevant to this thread):

AV Rule 209 (MISRA Rule 13, Revised)
The basic types of int, short, long, float and double *shall not* be
used, but specific-length
equivalents should be typedef'd accordingly for each compiler, and these
type names used in
the code.
Rationale: Since the storage length of types can vary from compiler to
compiler and
platform-to-platform, this rule ensures that code can be easily
reconfigured for storage size
differences by simply changing definitions in one file. See AV Rule 209
in Appendix A for
additional details.
Exception: Basic types are permitted in low-level routines to assist in
the management of
word alignment issues (e.g. memory allocators).
MISRA rule was changed from should to shall.

/Flibble
0 new messages