clibnetsignedness

Function return type is unsigned while it returns -1 for error


I've been using libnet for a while and I've noticed there are some functions which return value is uint32_t which, from my understanding, is a unsigned type. However, in the documentation, it says to return -1 if an error occurred(which is a signed type) See libnet_get_ipaddr4, libnet_get_prand, for example.

However, I've busing such functions with no problem:

if ((src_ip_addr = libnet_get_ipaddr4(l)) == -1) { /* treat the failure*/ }

I suppose that comparison takes place between -1 interpreted as unsigned int against the return value which takes the same value; comparison is true.

Even though this apparently works, my question is: Does this make sense? Why? As a programmer, how should I check the return value to know if an error occurred? Is the code snippet shown above correct?


Solution

  • Quoting C99 standard draft, 6.2.5.9:

    A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.

    So -1 is automatically converted to UINT32_MAX.

    Warning: Dealing with out-of-range values is not as nice for signed types. See here and here for various complications.

    6.5.9 says that for equality operators,

    If both of the operands have arithmetic type, the usual arithmetic conversions are performed.

    6.3.1.8 describes these conversions:

    [...] Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type. [...]

    (You can hunt through the standard for similar justification for returning -1 for a function returning a signed type, but it's basically the same argument, so I won't bother.)

    In other words, yes this is perfectly correct.