Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

comparing unsigned vs signed does not make a warning (using const)

Tags:

c

gcc

constants

Simple: If I test a signed vs an unsigned variable in GCC, when compiling -Wall I will get a warning.

Using this code:

#include <stdio.h>

int main(int argc, char* argv[])
{
    /* const */ unsigned int i = 0;
    if (i != argc)
        return 1;
    return 0;
}

I get this warning:

<source>: In function 'int main(int, char**)':
<source>:6:8: warning: comparison of integer expressions of different signedness: 'unsigned int' and 'int' [-Wsign-compare]
    6 |  if (i != argc)
      |      ~~^~~~~~~
Compiler returned: 0

However, if I uncomment this const - the compiler is happy. I can reproduce this on almost every GCC version (see https://godbolt.org/z/b6eoc1). Is is this a bug in GCC?

like image 389
elcuco Avatar asked Jan 18 '21 14:01

elcuco


2 Answers

I think that what you are missing is compiler optimization. Without const, that variable is a variable, meaning that it can change. Since it is an unsigned int, it means that indeed it can be larger than an integer.

const unsigned int i = 2147483648;

You will get your error back if you assign a value greater than the largest value of int to that unsigned int.

However if it is const, the compiler knows its value, it knows, that it will not change, and there will be no problem with the comparison.

If you take a look at the assembly, you will see that without const, it actually takes the value of the variable to compare:

movl    $0, -4(%rbp)
movl    -20(%rbp), %eax
cmpl    %eax, -4(%rbp)

Now, if it is const, it will not bother with the variable at all, it just takes the value:

movl    $0, -4(%rbp)
cmpl    $0, -20(%rbp)
like image 172
Marcell Juhász Avatar answered Oct 06 '22 16:10

Marcell Juhász


I'd say it's a compiler bug in the -Wsign-compare option.

Test by compiling your example with -Wall -Wextra -O3. With -O3 added, the warning suddenly goes away in the const case. Even though the generated machine code with or without const is identical. This doesn't make any sense.

Naturally, neither const nor the generated machine code has any effect on the signedness of the C operands, so the warning shouldn't come inconsistently depending on type qualifiers or optimizer settings.

like image 2
Lundin Avatar answered Oct 06 '22 16:10

Lundin