cif-statementtype-conversionsize-tequality-operator

Comparing size_t to -1


Note: it has been suggested that this question duplicates Can I compare int with size_t directly in C?, but the question here specifically asks about comparing size_t with a negative value. For this reason, it should be re-opened. (And besides, it has generated a lot of thoughtful discussion!)

I'm staring at some library code (I am looking at you, Microchip), declared to return a size_t:

size_t SYS_FS_FileWrite(SYS_FS_HANDLE handle, const void *buf, size_t nbytes);

That is documented as returning -1 on an error. But size_t is an unsigned value. So, in theory and/or in practice, is the following allowed?

if (SYS_FS_FileWrite(handle, buf, nbytes) == -1) {
    report_errror();
}

Solution

  • It is impossible for a routine that returns a size_t to return −1, but it is perfectly fine for it to return the result of converting −1 to size_t (presuming the relevant environment does not need that value for any conflicting purpose). If the documentation states the latter, it is fine. If it states the former, the documentation is sloppily written and probably means the latter.

    In a comparison of some size_t value x to -1, as in x == -1, the value −1 will be converted to the type size_t if the rank of size_t equals or exceeds the rank of int. This is the case in most C implementations and would be expected in an implementation that uses −1 converted to size_t as a return value. In a C implementation in which size_t had lower rank than int, x could be converted to int (depending on some specifics of the types). That would not change the value, and x == -1 would always evaluate as false.

    Per a request in the comments for a test of whether SYS_FS_FileWrite(handle, buf, nbytes) == -1 is a safe test for SYS_FS_FileWrite returning −1 converted to size_t in light of the fact that the usual arithmetic conversions might not produce the desired results, a suitable test is _Static_assert((size_t) -1 == -1, "size_t type is too narrow.");. Also, the test could be written as SYS_FS_FileWrite(handle, buf, nbytes) == (size_t) -1.