- Avoid 'int' and associates. - 10 Updates
- A confusing topic in Stroustrup's book - 1 Update
- Confusing passage in C++ book - 1 Update
- Zeroing in the constructor - 1 Update
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
Subscribe to:
Post Comments (Atom)
|
No comments:
Post a Comment