Remix.run Logo
cperciva 13 hours ago

I don't get it. Is this a parody of poor design decisions?

Sure, it's possible to write bugs in C. And if you really want to, you can disable the compiler warnings which flag tautologous comparisons and mixed-sign comparisons (a common reason for doing this is to avoid spurious warnings in generic-type code).

But, uhh, "people can deliberately write bugs" has got to be the weakest justification I've ever seen for changing a language feature -- especially one as fundamental as "sizes of objects can't be negative".

adrian_b 13 hours ago | parent [-]

The C language does not have any data type that has the property "can't be negative".

Signed integers can be negative. The so-called "unsigned" integers of C are integer residues modulo 2^N, which are neither positive nor negative, i.e. these concepts are not applicable to "unsigned" integers.

An alternative view is that any C "unsigned" is both positive and negative. For example the unsigned short "1" is the same number as "65537" and as "-65535".

So any sizeof value in C is negative (while also being positive).

In contradiction with what you say, the change described in TFA, by making sizes 64-bit signed integers, is the only method to guarantee that the sizes are non-negative in a language that does not have dedicated non-negative integers.

Other programming languages have non-negative integers, but C and C++ and many languages derived from them do not have such integers.

The arithmetic operations with non-negative integers differ from the arithmetic operations of C. On overflows and underflows, they either generate exceptions or have saturating behavior.

alberto-m 12 hours ago | parent | next [-]

> An alternative view is that any C "unsigned" is both positive and negative. For example the unsigned short "1" is the same number as "65537" and as "-65535".

This can be disproven by the fact that dividing by `unsigned e = 1U` is well defined and always yields the starting number. If the unsigned numbers were really modular numbers as you suggest, division could not be defined.

adrian_b 12 hours ago | parent [-]

This does not demonstrate anything. It is just additional evidence that the C standard contains contradictory rules about "unsigned" integers.

The oldest parts of the C language are all consistent with "unsigned" numbers being non-negative integers. The implicit conversions between different sizes of "unsigned", the sizeof operator, the relational operators and division are consistent with non-negative integers.

However the first C standard, instead of defining the correct behavior has left undefined many corner cases of the arithmetic operations, allowing the implementation of "unsigned" as either non-negative integers or integer residues.

Eventually, the undefined behaviors for addition, subtraction and multiplication have been defined to be those of integer residues, not those of non-negative integers.

These contradictory properties are the cause of many confusions and bugs.

In extensible languages, like C++, it is possible to define proper non-negative integers and integer residues and bit strings and to always use those types instead of the built-in "unsigned".

In C, it is better to always use signed numbers and avoid unsigned, by casting unsigned to bigger sizes of signed before using such a value.

marshray 12 hours ago | parent | prev | next [-]

Are you claiming that the following program could possibly print "-1" ?

    #include <stdio.h>
    int main() {
        unsigned short a = 1;
        long b = a;
        printf("%ld\n", b);
    }
If not, why?
cperciva 12 hours ago | parent | prev [-]

Leaving aside the fact that, yes, unsigned integer types are definitely not negative -- my point wasn't about types at all. Objects cannot take up a negative number of bytes of memory!