A short int always declares an integer that has one half the number of bits of a regular int.

On Sat, 31 Jul 1999 03:56:23 -0500,
(blargg) wrote:

>> In cryptographic applications as well as many other situations>> integers of specific bit sizes are required.>>And in many programs, they aren't required. Too often code is written to

>depend on these bit sizes even though it is unnecessary.

This is true and I agree totally. But then, there is also no need to
#include inttypes.h in that cases.

My article, however, was addressed to the remaining cases, where bit
size IS significant for code functionality.

>Sorry, try again. There is no guarantee that an int uses all pf its>storage for representing its value. sizeof (int) could be 4, even though

>only 2 bytes of it are used for value representation (16 bits).

Yes, but at least for calculating the storage size in bits the formula
is nevertheless valid.

Nevertheless, this your point is a valid argument otherwise. There is
really no guarantee that UINT_MAX may not be less than

1 << CHAR_BIT * sizeof(unsigned int)

This is one reason more to use carefully defined typedefs (such as
typedefs.h) in cases where bit size matters, because you are right:

Not even knowing that an unsigned int has 16 bits means that it must
be wide enough to store 1 << 16 possible values.

From that point of view, even the ANSI committee's minimum requirementof 16 bits for an integer becomes meaningless rubbish, because perhapsthere is a machine that wastes 8 bit for internal uses and only allows

to store a maximum value of 255 in an 16 bit integer.

However, types such as uint_fast16_t certainly refer to the CONTENTS avariable of such a type can store, not the exact bit size, becauseotherwise such a definition was just meaningless rubbish nobody could

use for nothing.

>Isn't this redundant? Since int is required to be at least 16 bits, code
>that uses int generally requires the fact that it can hold a 16-bit value.

Not due to your own argument: What if only 8 bits of this 16-bit int
are available for use?

So, following your own arguments, only an appropriate uint_fast16_t oruint_least16_t (or other tailored type) guarantees for the required

size.

>For example, isn't "int" one that is the fastest that can hold at least 16
>bits? I don't understand these.

Yes, but first: See your own argument above.

And second, there is no guarantee that an int is the fastest possible
type for ALL operations.

For instance, there could be a machine that performs most 16 and 32bit operations at the same speed. Naturally, int would be defined as32 bit on such a machine, because it is the 'mightier' type as usually

not slower.

But then, there may be a little difference, such as that dividing 16bit values is generally be done a few cycles faster that 32 bit

divisions.

In such situtations, uint_fast16_t may be mapped differtly than 'int'.

>This is interesting. It could be thought of as if inttypes provides the>basic types for the language, and then the "int" and "char" types are

>internally derived from these:

Yes, but I was not speaking of 'int' or 'char', but of 'uint16_t' etc.And there is no reason why a compiler should not provide

non-standard-types that can be exploited just for that reason.

> typedef int_fast16_t int;
> typedef int_least16_t short;

I do not think so. This looks rather like the attempt to redefine
standard types to me. :-)

But besides this, that would be only ONE possible variant. For other
compilers it may look quite differently, like this:

typedef __int32 int_fast16_t;typedef __int16 int_least16_t;

typedef __int64 int_fast64_t;

where '__int16' etc. are language extensions provided by the compiler.For instance, Visual C provides such constants. And there is no reasonwhy the inttypes.h implementation on such a platform should not usesuch extensions. There may even be no other alternatives for defining

a type (such as int_fast64_t on Visual C).

>For normal applications, I would expect them to use short, int, long, etc.
>Using these bit-sized things is junking up interfaces.

With "normal" I was referring to application that actually DO requirebit size guarantees. I agree that types such as 'uint64_t' should not

be used in applications where no such guarantee is required.

However, even to determine when a 'long' is required instead of an
'int' is a rather platform-specific decision.

From the portability viewpoint, any value that may exceed a value of
65535 should be declared as 'long'.

And due to your own argument, that perhaps not even all the guaranteed16 bits in an integer may be available to the application, evensmaller values may require a 'long' variable. (Although I have never

learned of such a machine.)

So, from a defensive point of view, ONLY using inttypes.h guarantees
ANYTHING.

Normal programmers, however, will assume that an unsigned int CANstore at least the value 65535. Me too, besides. (But only usinguint_fast16_t or uint_least16_t may provide any absolute guarantee for

this.)

>No, this is not similar. Using "int" and "short" is similar to using>"double" and "float", but not similar to using "int_fast16_t" and

>"int_least16_t".

Why? "int" can be larger than "short", and "double" can be larger than"float". The same may be true for the exection speed. Either int/shortor double/float are similar to the fast/least types in that respect.

Also similarities are always relative.


>(gawd I hate those int_ names - who came up with them?)

Ever heard of some type named "size_t"? I think, it's from the same
group of people.

And then, nobody doubts that there are other ways to name the same
types.

But then, think of it the other way round:

The committee had to use names that were not in "heavy use" already,because otherwise name clashes were likely to occur in existing

applications.

They had to choose completely new identifiers that can be identifiedat the first glance - and I think the committee has done an excellent

job in this regard.

>> Following this path will make your applications portable to the>> highest degree possible (at least concering bit sizes).>

>No, it will only make it as portable as you made it.

But just this was intended when I wrote about "Following this path".

>If you depend on bit sizes in many places,>you could be breaking on machines that didn't meet

>those expectations. *not* using these can be the most portable.

Yes. But there are algorithms that simply can't be coded efficiently
without some bit size guarantees.

For instance, an implementation of the MD5-algorithm that is writtento work on 16-bit (only) CPUs will have to be written completelydifferent from implementations that assume some 32-bit data type is

available.

In such cases, your code REQUIRES bit size gurantees unless it's goingto be implemented hopelessly inefficient (such as using

single-bit-sequential calculations).

>> your would expect that the return value will always be in range from 0>> to 65535, would you?>>Not at all. uint_least16_t says nothing about how many bits it holds. It

>could be 1024 bits for all we care.

Well, be happy then: You are one of the smart guys then who got itright at the first reading. Unfortunately, not all people are as

clever as you are, so I decided to include that paragraph anyway.

>Why wouldn't one just mask with 0xFFFF? A decent compiler will optimize it.

Because not all compilers are as smart as you are either.

Also, you are free just mask it if you want. The intent for thisparagraph just was that it is important not to forget about the

masking.

>> return (uint_least16_t)(a + b & 0xffff);>>Fix your precedence levels.>> (a + b) & 0xffff>

>The cast would be unnecessary.

First of all, "+" has a higher precedence than "&", so

a + b & 0xffff

is absolutely correct. Perhaps YOU should check your knowledge about
precendece levels.

Second, there is no guarantee that "+" or "&" applied to'uint_fast16_t' operands produces an 'uint_least16_t' result; hence

the cast IS necessary for the program to remain portable.

>> return (uint_least16_t)MASK16(a + b);>>How so? I think a decent compiler will optimize the mask into a move (or

>whatever) 16 bit.

But only if the processor provides an uint16_t compatible data type,which is not guaranteed. If the processor, for instance, only supports

8 and 64 bit moves, the masking will definitively be necessary.

And the MASK16() sample macro provides both capabilities, depending on
whether or not a native 16 bit type is available or not.

>> UINT16_C(0xffff)>> >> macro that has been used in the declaration: Such XintXXX_C(value)>> macros are another feature of inttypes.h. They add any necessary type>> suffix to the argument value to make it a valid literal constant for

>> the indicated type.

Note the use of the singular. "***a*** valid literal constant". No
plural.

> UINT16_C( 1 + 2 )>

>What does "adding a suffix" mean here?

The same as writing

1 + 2 h

for instance, namely nothing that makes sense. UINT16_C() is a macro
that may takes a SINGLE literal as its argument, such as:

#define __CONCAT(a, b) a##b#define UINT16_C(x) __CONCAT(x, h)

#define UINT64_C(x) __CONCAT(x, ui64)

which means that the correct usage is UINT16_C(1) + UINT16_C(2)
producing

1h + 2h

in this example mappings, where UINT64_C(1) + UINT64_C(2) would
produce

1ui64 + 2ui64

as a valid example for the Visual C compiler.

>Why wouldn't it be anyway? If it doesn't fit into an int, the compiler
>will treat the constant as a larger int type anyway.

I am not so sure about that. I can recall compiler warnings such as"constant is long" that were generated in such cases. From the mereexistence of such warnings, I conclude automatic promotion from int to

long is NOT part of the language specification.

>> which will add the 'L'-suffix automatically where necessary.>

>This seems pointless, at least for what you're using it for.

See above.

>Didn't you state at the beginning of the article that it's going to be
>included already? "The soon-to-come standard header file "inttypes.h"."

Yes, but unfortunately "soon-to-come" only for ISO C-90, not C++.

And indeed, the file is available on many platforms (including LINUX
if my memory serves me right), but it is no standard yet.

It is prominent enough however, that there is a GNU/AUTOCONF-macroavailable for checking whether inttypes.h is provided by the current

system of not.


Greetings,

Guenther--Note: the 'From'-address shown in the header is an Anti-Spamfake-address. Please remove 'nospam.' from the address in order

to get my real email address.

In order to get my public RSA PGP-key, send mail with blank body
to:
Subject: get 0x2D2F0683

Key ID: 2D2F0683, 1024 bit, created 1993/02/05
Fingerprint: 11 71 47 2F AF 2F CD F4 E6 78 D5 E5 3E DD 07 B5

Última postagem

Tag