1
#include <stdio.h>
int main()
{
    int size = sizeof(int);
    printf("%d\n", size);
    if(sizeof(int) > -1)
        printf("True\n");
    else
        printf("False\n");
        return 0;
}

This code is giving me the output False . But it should be true as we all know that the size of integer is 4.
But when I run the same code just typecasting the sizeof(int) in to an integer, It is giving me the output True .
Code which gives me correct output:

#include <stdio.h>
int main()
{
    int size = sizeof(int);
    printf("%d\n", size);
    if((int)(sizeof(int)) > -1)
        printf("True\n");
    else
        printf("False\n");
        return 0;
}

why this behavior is happening ?
Can you explain please?

  • Do you think `sizeof(int) > (size_t)-1` is 0 or 1? – chux - Reinstate Monica Sep 13 '22 at 13:09
  • Other, algebraically equivalent, code that gives the correct output would involve `sizeof(int) >= 0`. What's more, with that, you have a good chance of the compiler warning you that the comparison must always evaluate true on account of the range of `size_t`. – John Bollinger Sep 13 '22 at 13:11
  • I was about to say, your compiler really should have warned you about the comparison between signed and unsigned integer expressions. But two different compilers I tried didn't warn me either, not even when I specified `-Wall`, until I also specified `-Wextra`. Hmm. – Steve Summit Sep 13 '22 at 13:15
  • [Why sizeof(int) is not greater than -1?](https://stackoverflow.com/q/24466857/995714), [Why is −1 > sizeof(int)?](https://stackoverflow.com/q/3100365/995714) – phuclv Sep 13 '22 at 13:24
  • See [Implicit type promotion rules](https://stackoverflow.com/questions/46073295/implicit-type-promotion-rules). – Lundin Sep 13 '22 at 13:30

3 Answers3

2

The result of the sizeof operator has type size_t which is an unsigned type, so the expression sizeof(int) > -1 is comparing a signed integer with an unsigned integer.

In a case like this, the two operands are converted to a common type. In particular, given that a size_t is at least as large as an int (which is the type of the expression -1, the signed operand is converted to the type of the unsigned operand. This means the value -1 is converted to the largest value that can be stored in a size_t, so the comparison is false.

These conversion rules are called the usual arithmetic conversions and are spelled out in section 6.3.1.8p1 of the C standard (relevant passage in bold):

Many operators that expect operands of arithmetic type cause conversions and yield result types in a similar way. The purpose is to determine a common real type for the operands and result. For the specified operands, each operand is converted, without change of type domain, to a type whose corresponding real type is the common real type. Unless explicitly stated otherwise, the common real type is also the corresponding real type of the result, whose type domain is the type domain of the operands if they are the same, and complex otherwise. This pattern is called the usual arithmetic conversions:

  • First, if the corresponding real type of either operand is long double, the other operand is converted, without change of type domain, to a type whose corresponding real type is long double.
  • Otherwise, if the corresponding real type of either operand is double, the other operand is converted, without change of type domain, to a type whose corresponding real type is double.
  • Otherwise, if the corresponding real type of either operand is float, the other operand is converted, without change of type domain, to a type whose corresponding real type is float.
  • Otherwise, the integer promotions are performed on both operands. Then the following rules are applied to the promoted operands:
    • If both operands have the same type, then no further conversion is needed.
    • Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank.
    • 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.
    • Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, then the operand with unsigned integer type is converted to the type of the operand with signed integer type.
    • Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type.

And the mechanics of how the conversion happens is spelled out in section 6.3.1.3p2:

Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.

dbush
  • 205,898
  • 23
  • 218
  • 273
0

Due to the usual arithmetic conversions if in an expression one operand has an unsigned integer type and other has a signed integer type and the rank of the unsigned integer type is greater than or equal to the rank of the signed integer type then the operand with the signed integer type is converted to the unsigned integer type.

In the condition of this if statement

if(sizeof(int) > -1) 

the expression sizeof( int ) has the unsigned type size_t (that usually corresponds to the type unsigned long int) the rank of which is greater than the rank of the type int that is the type of the integer constant -1;

So the expression -1 is converted to the type size_t by propagating the sign bit and as a result is converted to a very big unsigned integer value.

Here is a demonstration program

#include <stdio.h>

int main( void ) 
{
    printf( "( int )-1 = %d\n", -1 );
    printf( "( size_t )-1 = %zu\n", ( size_t )-1 );
}

The program output is

( int )-1 = -1
( size_t )-1 = 18446744073709551615

In the condition of the second if statement

if((int)(sizeof(int)) > -1)

the both operands have the signed type int due to the explicit casting the first operand to the type int. So neither conversion takes place and the operand -1 has the negative value -1.

Pay attention to that there is a nuance. In some implementations the size of the unsigned type unsigned long int (or of size_t) is equal to the size of the signed type signed long long int.

In means that objects of the type signed long long int are unable to represent all values of the type unsigned long int.

So in expressions with operands of the type signed long long int and the type unsigned long int the both operands are converted to the type unsigned long long int again due to the same usual arithmetic conversions. and if you will write for example

if ( sizeof(int) > -1ll)

where there is used the operand -1ll of the type signed long long int the rank of which is greater than the rank of the operand of the type size_t nevertheless the condition again will be evaluated to false because the operand -1ll will be converted to the type unsigned long long int.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
-3

You need to cast it because sizeof() returns number of bytes but the return type is unsigned and you are trying to store it in an int type variable.

Dany
  • 37
  • 5
  • Your answer doesn't describe why they encounter what they do. They're also not storing the size in an `int` variable here. Your edited answer is still wrong, they problem is not that they're trying to store the result of `sizeof` as an `int`, it's that they're implicitly converting the `int` with value `-1` to an unsigned value. – Thomas Jager Sep 13 '22 at 12:36