3

I think that the type names in Rust are much better than the ones in C. I'd choose f64 over double and u32 over unsigned int or uint_32t any day. Is there any reason (other than tradition) to use those counter-intuitive hard-to-learn names?

I know that names like short and long are architecture-specific, but doesn't that make the actual problem even worse? C is said to be "portable assembly", but in the assembly language you actually have to use the correct registers and sizes, which are defined by architecture, just as in C. Therefore I'm not sure how this actually helps us to produce better code (in terms of readability).

The only problem I could think of is about byte size. If byte isn't eight bits, then using bit-numbers in type names wouldn't be so clever. But then, why don't we use some clear names that tell us exact multiples of byte that the datatype contains, like sb (single byte), db (double byte), qb (quad byte)?

So, why do we use architecture-specific type names in C, even when it is not necessary?

7
  • I think you started off writing a question about Rust and ended up writing a question about C. Your title and question body don't match.
    – MetaFight
    Commented Jun 11, 2016 at 21:25
  • @MetaFight good point, I edited the title Commented Jun 11, 2016 at 21:27
  • 3
    We use integral types of implementation-defined size when this is the semantics we want. (For example, if we want the machine's native type.) We use the fixed-width types defined in stdint.h if we care about the exact sizes.
    – 5gon12eder
    Commented Jun 11, 2016 at 21:32
  • 1
    You have it exactly backwards. uint_32t is architecture-specific, while unsigned int is architecture-agnostic. Some C-compliant computers (meaning a computer for which a compiler compliant with the C standard exists) do not have a 32 bit unsigned integer. On those computers, there is no such thing as uint_32t, but there still is an unsigned int type. Commented Jun 11, 2016 at 22:22
  • 1
    int, float, and double are counter-intuitive and hard to learn? Really?
    – John Bode
    Commented Jun 15, 2016 at 16:25

1 Answer 1

6

Because the C language is designed to be implementable on any platform, no matter what set of integer sizes it natively provides.

In fact, none of the intN_t types are guaranteed to exist at all. Only an implementation which provides a two's complement signed integer of exactly N bits (no padding bits allowed) will define the corresponding intN_t type (see section 7.20.1.1 of the C11 standard).

The char, int, long, etc types are all guaranteed to exist, and they are guaranteed to allow certain ranges of values (see section 5.2.4.2.1 of the C11 standard), but they might not be two's complement, they might allow more values than just the required range, they might all be the same type in the underlying implementation, and they might even be implemented in software instead of hardware. In other words, the "normal" integral C types guarantee absolutely nothing except a range of values that they can be assigned. That is what makes them maximally portable.

Of course, in practice the main reason we're still using char, int, long, etc is because that's all C had for a long time, that's what everyone's used to using, and the technical differences between char, int8_t, uint8_t, int_least8_t, int_fast8_t and so on simply don't matter to a great deal of code.

But if you do care about getting the optimal types, or you're on one of the projects where these distinctions do matter, then it's worth pointing out that the int_leastN_t and int_fastN_t types are guaranteed to exist on all conforming implementations (see sections 7.20.1.2 and 7.20.1.3 of the C11 standard), which means they have a huge portability advantage over the intN_t types.

As for Rust, what I've managed to gather from their documentation is this: Rust's integer types have to exist in all conforming Rust implementations, the signed ones are required to use two's complement, they have to have defined overflow behavior, and I can't find any evidence of a "no padding bits" requirement. In other words, Rust integer types are not even close to a perfect match for any of the C11 integer types.

2
  • "the int_leastN_t and int_fastN_t types are guaranteed to exist" only applies for N = 8,16,32,64 (and their unsigned counter parts)
    – chux
    Commented Jun 19, 2016 at 15:37
  • @chux I assumed I could omit that clarification since that's the same set of N values as for the intN_t types. Feel free to suggest another edit if you think it's not clear enough already.
    – Ixrec
    Commented Jun 19, 2016 at 16:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.