Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

3-byte int and 5-byte long?

Tags:

c++

c

sizeof

Does each of C and C++ standards allow sizeof of numeric types not to be a power of two?

The following constraints are known:

  • 16 <= CHAR_BIT * sizeof(int) <= CHAR_BIT * sizeof(long)
  • 32 <= CHAR_BIT * sizeof(long) <= CHAR_BIT * sizeof(long long)
  • and a dozen of others, which on a typical 8-bit byte architecture means 2 <= sizeof(int) && 4 <= sizeof(long)

Does that mean that sizeof(int) == 3 && sizeof(long) == 5 is a valid behaviour?

If yes - is there any known compiler/architecture behaving in a similar way?

like image 322
sasha.sochka Avatar asked Jul 24 '13 13:07

sasha.sochka


People also ask

How many bytes is a long long?

The size of the long type is 8 bytes (64 bits). The minimum value is -9 223 372 036 854 775 808, the maximum value is 9 223 372 036 854 775 807.

How long is an int in bytes?

The int and unsigned int types have a size of four bytes.


2 Answers

I think 3.9.1/2 (C++98) sums this up nicely (immediately followed by analogous information for the unsigned types):

There are four signed integer types: “signed char”, “short int”, “int”, and “long int.” In this list, each type provides at least as much storage as those preceding it in the list. Plain ints have the natural size suggested by the architecture of the execution environment39) ; the other signed integer types are provided to meet special needs.

Basically all we know is that sizeof(char) == 1 and that each "larger" type is at least that large, with int being a "natural" size for an architecture (where as far as I can tell "natural" is up to the compiler writer). We don't know anything like CHAR_BIT * sizeof(int) <= 32 etc. Also keep in mind that CHAR_BIT doesn't have to be 8 either.

It seems fairly safe to say that three byte int and five byte long would be allowed for hardware where those sizes were natively used. I am however not aware of any such hardware/architectures.

EDIT: As pointed out in @Nigel Harper comment we do know that int has to be at least 16 bits and long at least 32 bits to satisfy range requirements. Otherwise we don't have any specific size restrictions other than as seen above.

like image 163
Mark B Avatar answered Sep 30 '22 18:09

Mark B


TL;DR

The behavior is valid and such compilers/architectures do exist

  • TI C5500/C6000 with 4-byte int, 5-byte long
  • Motorola DSP5600x/3xx series with 2-byte short, 3-byte int, 6-byte long
  • x86 with 8-byte double, 10-byte long double

The number of bits used to represent the type long is not always the same as, or an integer multiple of, the number of bits in the type int. The ability to represent a greater range of values (than is possible in the type int) may be required, but processor costs may also be a consideration...

Derek M. Jones' The New C Standard (Excerpted material) - An Economic and Cultural Commentary


The other answer have already recapped C++ standard requirements. Similarly C standard also doesn't constrain the type (floating-point or integer) sizes in bytes to powers of 2. The most common example is long double, which is most often 10 bytes in x86 (with padding to 12 or 16 bytes in many modern compilers).

ISO/IEC 9899:1999 (E)

5.2.4.2.1 Sizes of integer types <limits.h>

  1. The values given below shall be replaced by constant expressions suitable for use in #if preprocessing directives. Moreover, except for CHAR_BIT and MB_LEN_MAX, the following shall be replaced by expressions that have the same type as would an expression that is an object of the corresponding type converted according to the integer promotions. Their implementation-defined values shall be equal or greater in magnitude (absolute value) to those shown, with the same sign. [...]

6.2.5 Types

  1. There are five standard signed integer types, designated as signed char, short int, int, long int, and long long int. (These and other types may be designated in several additional ways, as described in 6.7.2.) There may also be implementation-defined extended signed integer types.28)

    The standard and extended signed integer types are collectively called signed integer types.29)

  2. For any two integer types with the same signedness and different integer conversion rank (see 6.3.1.1), the range of values of the type with smaller integer conversion rank is a subrange of the values of the other type.


Odd-sized integer types are much rarer, but still exist. Many DSPs have standard-conforming compilers with non-power-or-2 types where int has 32 bits, long has 40 bits.

long is

  • 40 bits or 5 bytes for C6000 COFF. This is fully compliant with any major C/C++ standard as those standards are all defining a minimum requirement of 4 byte for long (aka. long int). Programmers are often falsely assuming this type having a size of exactly 4 bytes.

Emphasis mine
C89 Support in TI Compilers#Misunderstandings about TI C

Offside note: On some TI targets even long long is also a 32 or 40-bit type, which is valid in C89 as an extension but violates C99

Some targets have long long (an extension from C99), but not a conforming one. C99 requires at least 64 bits, but C2700 has 32-bit long long, and C5500 has 40-bit long long. C2800, C6000, and ARM have 64-bit long long, and C5400 and MSP430 do not support long long. This is not technically a violation of C89, since this is actually an extension, but if we start supporting C99, this would be a violation of C99 (C99 5.2.4.2.1 "Sizes of integer types <limits.h>" para 1).

The wider type's size doesn't even have to be a multiple of its preceding type's size. Continuing with what Derek M. Jones said in The New C Standard (Excerpted material): An Economic and Cultural Commentary

... For instance, the Texas Instruments TMS320C6000, a DSP processor, uses 32 bits to represent the type int and 40 bits to represent the type long (this choice is not uncommon). Those processors (usually DSP) that use 24 bits to represent the type int, often use 48 bits to represent the type long. The use of 24/48 bit integer type representations can be driven by application requirements where a 32/64-bit integer type representation are not cost effective.

In all 24-bit DSPs I had known before, CHAR_BIT == 24 and all types have sizes as multiples of 24 bits, but I've just found out that the Motorola DSP5600x/3xx series have a really "strange" type system

Data Type size in bits
(un)signed char 8
(un)signed short 16
(un)signed int 24
(un)signed long 48
(long)_fract 24 (48)
pointer 16/24
float/double 24+8
enum 24

So in this case sizeof(char) == 1 and sizeof(short) == 2 but sizeof(int) == 3 and sizeof(long) == 6

Unfortunately GCC calls them (long and long long) double-word integers, and so do most people, making a big misunderstanding, although it doesn't necessarily be double the size.

like image 33
phuclv Avatar answered Sep 30 '22 16:09

phuclv