longs, long longs, short short long ints . . . huh?!

D

David Geering

Is there any standard as to what a long and int mean or is it compiler
dependent? Or furthermore architecture dependent?

I know a short short long int isn't actually a recognised type, but if you
wanted to make sure it was 16-bit, 32-bit or 64-bit etc, can you rely on
these type names alone? If not, is there any way to ensure you get a
64/32/16-bit int when you want one?

Cheers,
Dave.
 
S

slebetman

David said:
Is there any standard as to what a long and int mean or is it compiler
dependent? Or furthermore architecture dependent?

It's compiler and architecture dependent. C only specifies the minimum
size of a type, not it's actual implemented size. To comply with C, int
needs to be at least 16 bits, long needs to be at least 32 bits and
long long needs to be at least 64 bits. A compiler may decide to
implement int == long == long long == 64 bits on any platform (It's
common nowdays to see 32 bit ints on 8 bit platforms).
I know a short short long int isn't actually a recognised type, but if you
wanted to make sure it was 16-bit, 32-bit or 64-bit etc, can you rely on
these type names alone? If not, is there any way to ensure you get a
64/32/16-bit int when you want one?

I usually use one of 2 methods:

If the data is not arithmetic and I'm only doing bitwise operations on
it then I treat it as a byte array. This is not 100% portable since I
make the assumption that a byte is exactly 8 bits (though this method
does not really depend on the assumption, it's easier with the
assumption).

If the data is arithmetic then choose the largest size to properly
represent the data and use masking to truncate the data.

The real issue of wanting an exact bitlength of a datatype is when you
want to communicate the data with an external program either via
transmitting it or saving it to file. There are lots of threads
discussing this issue but usually under the heading of endianness and
portability. But the advice is still useful here. Read/write the data a
byte at a time using shift operators. This allows you to discard/ignore
the extra bits in the variable if it happens to have more bits than you
intended.
 
S

santosh

David said:
Is there any standard as to what a long and int mean or is it compiler
dependent? Or furthermore architecture dependent?

Their exact size and range are implementation specific. Apply the
sizeof operator to get the size in bytes, (a byte is not necessarily an
octet in C), and use the macros defined in limits.h and float.h to find
out the range.

The standard does specify certain minimum requirements that all
conforming implementations must meet. See section 5.2.4.2 of the C99
draft at the link below:
I know a short short long int isn't actually a recognised type, but if you
wanted to make sure it was 16-bit, 32-bit or 64-bit etc, can you rely on
these type names alone? If not, is there any way to ensure you get a
64/32/16-bit int when you want one?

C99 has defined a bunch of new types for these purposes. They're
defined in stdint.h and some associated format specifiers for doing I/O
with them are in inttypes.h. For example if you need a type whose size
is exactly 32 bits, use int32_t or uint32_t.

Look up these standard header files on your system.

Also look up section 7.18 and 7.8 of the draft linked above.
 
C

CBFalconer

santosh said:
David Geering wrote:
.... snip ...


C99 has defined a bunch of new types for these purposes. They're
defined in stdint.h and some associated format specifiers for
doing I/O with them are in inttypes.h. For example if you need a
type whose size is exactly 32 bits, use int32_t or uint32_t.

Look up these standard header files on your system.

And then avoid using them. They are not required, and the result
is non-portable code.
 
S

santosh

CBFalconer said:
And then avoid using them. They are not required, and the result
is non-portable code.

The OP did ask for types of specific width. He should be aware that
they may not be defined for all implementations.
 
D

David Geering

If the data is arithmetic then choose the largest size to properly
represent the data and use masking to truncate the data.

Thanks all to the advice and comments. Usually I will be dealing with
arithmetic operations so I will take your advice and truncate. It is all
unsigned data as well so it would make it quite simple.

Thanks again.
 
J

Jack Klein

And then avoid using them. They are not required, and the result
is non-portable code.

They ARE required for any even slightly conforming C99 compiler, and
are available with most current C90 versions as extensions.

And it is quite easy to roll your own on virtually every
implementation that supports the underlying types. With the exception
of the 64-bit types, that includes all the compilers used by 98% or
99% of all the working C programmers in the world.

One of the reasons that C99 is so poorly supported is that C
programmers who know about it advise others not to use its features
because they are not widely supported. That's a vicious circle.

If certain posters here spent as much time lobbying their compiler
vendors/suppliers to implement the current C standard as they did
advising others not to use it, perhaps the situation would change.
 
I

Ian Collins

Jack said:
One of the reasons that C99 is so poorly supported is that C
programmers who know about it advise others not to use its features
because they are not widely supported. That's a vicious circle.

If certain posters here spent as much time lobbying their compiler
vendors/suppliers to implement the current C standard as they did
advising others not to use it, perhaps the situation would change.
Well said!
 
C

CBFalconer

Jack said:
They ARE required for any even slightly conforming C99 compiler, and
are available with most current C90 versions as extensions.

And it is quite easy to roll your own on virtually every
implementation that supports the underlying types. With the exception
of the 64-bit types, that includes all the compilers used by 98% or
99% of all the working C programmers in the world.

One of the reasons that C99 is so poorly supported is that C
programmers who know about it advise others not to use its features
because they are not widely supported. That's a vicious circle.

I'm not doing that. The point is that those definitions may not be
available on the destination, regardless of the standard in
effect. In general they are unnecessary in non-system code. The
only real use, to me, is to force compilation errors when the
implementation is unsuitable.
 
K

Keith Thompson

Jack Klein said:
They ARE required for any even slightly conforming C99 compiler, and
are available with most current C90 versions as extensions.

I agree with your overall argument, but you missed the specific point
about the exact-width types.

The <stdint.h> header is required. The exact-width types are not.
For example, a implementation will not provide int32_t *unless* it
happens to have a signed integer type with width 32, no padding bits,
and a two's complement representation. (And yes, I've used a system
that had no such type -- though it didn't have a C99 compiler either.)
And it is quite easy to roll your own on virtually every
implementation that supports the underlying types. With the exception
of the 64-bit types, that includes all the compilers used by 98% or
99% of all the working C programmers in the world.

I agree that providing your own <stdint.h> for implementations that
don't have it is fairly straightforward. See, for example, Doug
Gwyn's public-domain q8 at <http://www.lysator.liu.se/c/q8/index.html>.
 
R

Richard Heathfield

Jack Klein said:

If certain posters here spent as much time lobbying their compiler
vendors/suppliers to implement the current C standard as they did
advising others not to use it, perhaps the situation would change.

But "certain posters here" (amongst whose number I unhesitatingly include
myself) are interested not in change for the sake of change, but in writing
portable C programs. This is already possible in C90, so why bother
lobbying? Those who need portability can ignore C99. Those who desire its
features can embrace them if they are prepared to pay the portability cost.

The only ones who need to lobby implementors are those who desire C99's
features *and* portability. For such people, lobbying one implementor is
insufficient. They need to lobby *all* the implementors whose
implementations they use and which do not yet conform to C99.

Good luck with that, but I'm not holding my breath.
 
S

Spoon

David said:
Is there any standard as to what a long and int mean or is it compiler
dependent? Or furthermore architecture dependent?

I know a short short long int isn't actually a recognised type, but if you
wanted to make sure it was 16-bit, 32-bit or 64-bit etc, can you rely on
these type names alone? If not, is there any way to ensure you get a
64/32/16-bit int when you want one?

POSIX defines the stdint.h header.
http://www.opengroup.org/onlinepubs/000095399/basedefs/stdint.h.html

Note: my answer is off-topic for comp.lang.c
cf. comp.unix.programmer to discuss POSIX.
 
M

Malcolm McLean

David Geering said:
Thanks all to the advice and comments. Usually I will be dealing with
arithmetic operations so I will take your advice and truncate. It is all
unsigned data as well so it would make it quite simple.
It's not often that you need a number modulus a power of two power of two.
It's even rarer that using the free modulus due to overflow makes an
appreciable difference to program run time.

Join my campaign for 64 bit ints and just store everything in ints and have
done.
 
R

Richard Bos

CBFalconer said:
And then avoid using them. They are not required, and the result
is non-portable code.

Depends on what you want, and what you use. _If_ you have C99, or a
hand-hacked header for C89, which is simple enough to make, then:

- the header _must_ supply int_least8_t, int_least16_t, int_least32_t
and int_least64_t, so if what you want is a type that's guaranteed to
have at least that many bits, and by preference no more than necessary,
you can use these;
- if you really need _exactly_ 16, 32, and 64-bit types, you can safely
use int32_t et. al., since if a C99 implementation doesn't have these,
it doesn't have any other type you can use, either. This is because _if_
the implementation supplies any integer of exactly 8, 16, 32 or 64 bits,
it _must_ also supply the corresponding intN_t.

Richard
 
K

Keith Thompson

- if you really need _exactly_ 16, 32, and 64-bit types, you can safely
use int32_t et. al., since if a C99 implementation doesn't have these,
it doesn't have any other type you can use, either. This is because _if_
the implementation supplies any integer of exactly 8, 16, 32 or 64 bits,
it _must_ also supply the corresponding intN_t.

Assuming that the type has a two's complement representation and no
padding bits.

Even if the implementation doesn't provide int32_t, you can have a
type that's exactly 32 bits as long as 32 % CHAR_BIT == 0:
unsigned char[32/CHAR_BIT]
To perform arithmetic operations, you can copy the value to an object
of type long or unsigned long (which is guaranteed to be big enough).
This could be useful if you need to use some externally imposed data
format.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,733
Messages
2,569,440
Members
44,832
Latest member
GlennSmall

Latest Threads

Top