NO warning signed unsigned int, with -Wall?

hello,
i have some question about signed unsigned compare.

Following code drops me an warning
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <string>

int main(void)
{
	int test_1 = -1000;
	unsigned int test_2 = 1000;
	if(test_1 < test_2)
		std::cout << "test_1 < test_2" << std::endl;
	else
		std::cout << "test_1 >= test_2" << std::endl;
	return 1;	
}

Message:
g++ test.cpp -o test.exe -Wall
test.cpp: In function 'int main()':
test.cpp:8:12: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
if(test_1 < test_2)
~~~~~~~^~~~~~~~


Following source code drops NO warning why?
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <string>

int main(void)
{
	int16_t test_1 = -1000;
	uint16_t test_2= 1000;
	if(test_1 < test_2)
		std::cout << "test_1 < test_2" << std::endl;
	else
		std::cout << "test_1 >= test_2" << std::endl;
	return 1;
}


g++ cmd:
g++ test.cpp -o test.exe -Wall


Thanks a lot for your help!

Last edited on
Hi,

-Wall does not turn on all the warnings, compile with at least -Wall -Wextra -pedantic-errors

Also have a read of the manual, there are specific warnings about these things, and narrowing. I don't remember if the sign comparison is part of the options I mentioned. The narrowing one isn't included unless one specifically mentions it. There are other that could come in handy, like switch default.

Good Luck
Hello,
with the cmd:
g++ test.cpp -o test.exe -Wall -Wextra -pedantic-errors

drops NO warning, with the types int16_t and uint16_t.

it is the same issue.

thanks
Last edited on
TheIdeasMan wrote:
I don't remember if the sign comparison is part of the options I mentioned.


So, it looks like it isn't :+) Have a look at the gcc manual
Here's a piece to the puzzle:
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <string>

int main(void)
{
    short test_1 = -1000;
    unsigned short test_2 =  1000;
	if (test_1 < test_2)
		std::cout << "test_1 < test_2" << std::endl;
	else
		std::cout << "test_1 >= test_2" << std::endl;
	return 1;
}

also does not warn. So we know it's not a problem with the types defined in <cstdint>.

I would have to look at the assembly.
Here's the command I used. g++ test.cpp -S -Wall

test_int.s:
1
2
3
4
5
6
	call	__main
	movl	$-1000, -4(%rbp)
	movl	$1000, -8(%rbp)
	movl	-4(%rbp), %eax
	cmpl	%eax, -8(%rbp)
	jbe	.L2


test_short.s:
1
2
3
4
5
6
7
	call	__main
	movw	$-1000, -2(%rbp)
	movw	$1000, -4(%rbp)
	movswl	-2(%rbp), %edx
	movzwl	-4(%rbp), %eax
	cmpl	%eax, %edx
	jge	.L2


I'm no expert in assembly, but what I think is broadly happening here is an extra conversion. It's converting both the unsigned short and short to int. After the conversion, there's no comparisons between signed and unsigned ints, because both are converted to signed before the comparison.

I'll quote the following link
https://wiki.sei.cmu.edu/confluence/display/c/INT02-C.+Understand+integer+conversion+rules
Integer types smaller than int are promoted when an operation is performed on them. If all values of the original type can be represented as an int, the value of the smaller type is converted to an int; otherwise, it is converted to an unsigned int. Integer promotions are applied as part of the usual arithmetic conversions to certain argument expressions; operands of the unary +, -, and ~ operators; and operands of the shift operators.



Hope that clears it up a bit. I would be interested to see if the warning happens on compilers that are said to be better about warnings, like clang.
Last edited on
Topic archived. No new replies allowed.