Home > Back-end >  why size_t variable, int constant comparison doesn't work properly while off_t variable works f
why size_t variable, int constant comparison doesn't work properly while off_t variable works f

Time:03-26

I was trying to compare size_t(long int type for ubuntu) variable with int constant 0 but turned out not working properly. but off_t variable works fine.

size_t var = -3;

if(var < 0)
    putchar('X');
else
    putchar('Y');

// Y

but when I cast var into int, it works as I expect.

size_t var = -3;

if((int)var < 0)
    putchar('X');
else
    putchar('Y');

// X

but off_t(long int as well on my ubuntu) works fine without casting.

off_t var2 = -3;

if(var2 < 0)
    putchar('X');
else
    putchar('Y');

// X

Could you explain this please? Thanks.

CodePudding user response:

The type size_t is an unsigned type. So when you attempt to assign the value -3 to it, the value gets converted into a very large positive value. This is why the condition in the first case is false.

In the second case, when casting var to an int, the assigned value (i.e. the very large positive value from before) is outside the range of int so it gets converted in an implementation defined manner. On most implementations, this will result the value being converted to -3, so the condition will be true.

The type off_t is a signed type so it is able to store the value -3, so the comparison works as expected.

CodePudding user response:

size_t is an unsigned integer type, per C 2018 7.19 2. For illustration, in this answer I will treat it as 32 bits, with maximum value 4,294,967,295 (232−1), and I will treat int as 32 bits, with minimum value −2,147,483,648 and maximum value 2,147,483,647. Widths of integer types can differ between C implementations.

For size_t var = -3;, −3 is converted to the unsigned type. This conversion wraps modulo 4,294,967,296 (232), so 4,294,967,293 is stored in var.

In var < 0, the int 0 is converted to size_t. This does not change the value; the result of the conversion is 0, just with type size_t. Then the two size_t values 4,294,967,293 and 0 are compared. Since 4,294,967,293 is not less than 0, the result of the comparison is false (zero).

In (int)var < 0, the size_t var is converted to int. Since 4,294,967,293 is greater than our int can represent, the conversion is specified in C 2018 6.3.1.3 3, which says the result is implementation-defined. In common C implementations, it wraps modulo 232, in which case this conversion produces the value we started with −3. Then the int values −3 and 0 are compared. Since −3 is less than 0, the result of the comparison is true (one).

off_t is a signed integer type. (This is a Unix or other implementation-defined type, not a part of the C standard.) Since it is capable of representing −3, no change in value occurs when it is initialized with −3, and no change of value occurs when it is compared to 0.

  • Related