Bytes, chars, ints, etc (gnu algol 68, C, ...)

Jose E. Marchesi jemarch@gnu.org
Fri Jan 16 01:27:16 GMT 2026


>>> Hello All,
>>>
>>> Please let me know if this mail list is not the proper place for this
>>> kind of question.
>>
>> It is exactly the right place :)
>>
>>> Recent postings touch upon "bytes" (with respect to transput), and
>>> "chars" have been mentioned (with respect to unicode).
>>>
>>> Algol 68 was developed creating its own vocabulary for various datatypes.
>>>
>>> C has data types: "char", "int", etc.  Types sizes became more diverse
>>> yielding "short",  "int", "long int", "long long int".  Their actual
>>> sizes may vary from system to system.
>>>
>>> To clearly fix the sizes to a given name, some languages (for example
>>> zig) have created types such as:  unsigned integer types, "u8", "u16",
>>> "u32, "u64, and float types "f16", "f32", etc.  The naming discloses
>>> concrete numerical properties of each.
>>>
>>> Finally, here is the question:
>>>
>>> Given GNU Algol 68 shall be a superset, when introducing new primitive
>>> types must we restrict ourselves to the using the same/similar names
>>> used by "C"?  (And along with the "wiggle-room" on bytes sizes?)
>>>
>>> Or, would we be open for newer types with byte-size clarity from name.
>>> (Question motivated most recently  by the "byte, bits, etc for binary
>>> IO" postings.  Perhaps "u8" would be nice for this.)
>>
>> I have been actually reflecting about the possibility of having
>> size-named integral modes, as aliases to the corresponding `sizety int',
>> and I am coming to the conclusion that it may be not that good idea
>> after all.
>>
>> Thing is, in C you have types:
>>
>>     char
>>     short
>>     int
>>     long int
>>     long long int
>>
>>
>> which, depending on the target, may be of different sizes.  Also the
>> `char' may be signed or unsigned.
>>
>> For example, a typical 32-bit target:
>>
>>     char      8-bit (signed)
>>     short     16-bit
>>     int       32-bit
>>     long      32-bit
>>     long long 64-bit
>>
>> And a typical 64-bit target:
>>
>>     char      8-bit (signed)
>>     short     16-bit
>>     int       32-bit
>>     long      64-bit
>>     long long 64-bit
>>
>> Then C added types like int8_t, int16_t, int32_t and int64_t.  These are
>> aliases (typedefs) to the corresponding "unsized" type.  So in the
>> 32-bit target you have:
>>
>>     typedef char      int8_t;
>>     typedef short     int16_t;
>>     typedef int       int32_t;
>>     typedef long long int int64_t;
>>
>> This works well, in C.
>>
>> While discussing transput we thought about the possiblity of using a
>> similar strategy in GNU Algol 68.  The idea would be the same: lets
>> introduce aliases (mode names) with explicit sizes.
>>
>> For a typical 64-bit target:
>>
>>
>>     mode Int8  = short short int,
>>          Int16 = short int,
>>          Int32 = int,
>>          Int64 = long int;
>>
>>
>> For a typical 32-bit target:
>>
>>     mode Int8  = short short int,
>>          Int16 = short int,
>>          Int32 = int,
>>          Int64 = long int;
>>
>> Note that, unlike in C, they are the same in both arches!
>>
>> This is because, unlike in C, you cannot have a `long int' with the same
>> size than an `int'.  This is because the language rules say that if you
>> keep adding `long's at some point the precision "saturates" and further
>> additions don't have any further effect.  There is an enviroment enquiry
>> that tells you exactly how many `long's can you add that are actually
>> relevant.  Same consideration applies for shortsetys.
>>
>> This is documented in the report:
>>
>>   2.1.3.1 Plain values
>>
>>   [...]
>>
>>   b) An arithmetic value has a "size" i.e., an integer characterizing he
>>      degree of discrimination with which it is kept in the computer.
>>
>>   c) The mode of an integer or of a real number of size n is,
>>      respectively, some 'SIZETY integral' or 'SIETY real' here, if n is
>>      positive (zero, negative), that 'SIZETY' is n times 'long' (is
>>      empty, is -n times 'short').
>>
>>   d) The number of integers or of real numbers of a given size that can
>>      be distinguished increases (decreases) with that size until a
>>      certain size is reached, viz., the "number of extra lengths" (minus
>>      the "number of extra shorts") of integers or of real numbers,
>>      respectively, after which it is constant.
>>
>>
>> What I am coming to realize is that the C aliases would be pretty
>> useless for Algol 68.  This is because there are no implicit coercions
>> from, say, `short int' to `int'.  Widening only happens from int to real
>> of same sizety, and from real to complex of same sizety.  (Genie has an
>> extension to allow the other kind of coercions, but I don't want to
>> support it.)  This means that you would start writing something like the
>> following, to initialize a counter to zero:
>>
>>
>>      Int64 counter := _
>>
>>
>> and then, what, should you write:
>>
>>      Int64 counter := long 0;
>>
>> or should you write:
>>
>>      Int64 counter := long long 0;
>>
>> You see the point: the programmer needs to know the size of all the
>> supported `sizety int'.  If she doesn't, she will never be able to work
>> with the "sized" integral aliases.  And if she does, then she doesn't
>> need the sized integral aliases.
>>
>> HOWEVER...  this may be just fine.
>>
>> The reason why in C int64_t, etc, are so useful, is because given the
>> size of `int' you cannot really determine the size of the other types:
>> `long int' may be 32 bit, or 64.
>>
>>
>> But if to the existing Algol 68 rules we add a new one, as an extension,
>> saying that each increment (decrement) in size shall be doubling
>> (halving) the underlying number of bits, then given the size of `int and
>> the number of meaningful sizes, we can derive the size of any `SIZETY
>> int'.
>>
>> In other words, if `int' is 32-bit, `long int' will always be 64-bit, if
>> it is meaningful.  And `short int' and `short short int' will always be
>> 16-bit and 8-bit if they are meaningful.
>>
>> This could not accommodate targets with "non-regular" register sizes
>> such as 40 or 24 bits, but it _can_ accommodate true 16-bit targets, for
>> example, where you could have the following meaningful sizeties:
>>
>>
>>       short int -> 8-bit
>>       int       -> 16-bit
>>       long int  -> 32-bit
>>
>> And even true 8-bit targets:
>>
>>       int      -> 8-bit
>>       long int -> 16-bit
>>
>> So at this point my thinking (at least for now 8-)) is:
>>
>> 1. Adding explicitly sized integral mode names like Int64 and friends is
>>    not a good idea.
>>
>> 2. We should not fix Byte to be `short short int'.  It should be set by
>>    the compiler to be an alias to whatever `SIZETY int' mode is 8-bit.
>>
>> 3. There must be always a `SIZETY int' mode with size 8-bit.
>>
>> Thoughts?
>
> Just wanted to add a practical note.
>
> In all targets currently shipped in GCC, to the best of my knowledge,
> `int' is 32-bit.

Pietro points me out in IRC to the avr target, in which `int' is
actually 8-bit.

In any case, I think what follows stands..


> This means that in virtually every target used today,
>
>   `short short int' will be 8-bit.
>   `short int'       will be 16-bit.
>   `int'             will be 32-bit.
>   `long int'        will be 64-bit.
>   `long long int'   will be 128-bit (if supported by the arch).
>
> But, the proposed rule still allow supporting the language in
> architectures where you would typically use other compilers (even if
> there are some GCC ports available for these, off-tree) and where an
> `int' would need to be, for example, 16-bit, or even 8-bit.
>
> So, for all practical purposes, `long int' will always be 64-bit.
>
> Pietro: and this means we would have to change lseek to use `long int'
> and not `long long int'.


More information about the Algol68 mailing list