Compile this code with MSVC2005

unsigned short x = 20;
	unsigned short y = 20;

	for ( unsigned long i = 0; i < x * y ; i++ )
	{	
		cout<<i<<endl;
	}

and u get

warning C4018: '<' : signed/unsigned mismatch

why? i mean, it all runs fine, j is iterated till 400 and, as I know, the short unsigned should be converted in an unsigned long when doing the comparison, so no overflow cand be possible ... And, why is it stated signed/unsigned mismatch when all variables are unsigned and no overflow is possible?

thx in advance

Recommended Answers

All 10 Replies

To understand the reasoning of this execute the following:

int main() {
  std::cout<< sizeof( unsigned long) << ", " << sizeof( unsigned short ) ;

  return 0;
}

Basically short*short = short, but you're comparing this to a long. So there's a size mismatch. YOu could cast the shorts if you want to get rid of the warning or use only longs or shorts.

I think it's a very interesting question. From the C++ Standard (4.5, 1):

An rvalue of type char, signed char, unsigned char, short int, or unsigned short int can be converted to an rvalue of type int if int can represent all the values of the source type; otherwise, the source rvalue can be converted to an rvalue of type unsigned int.

No doubts that VC++ int type can represent all the values of unsigned short. So x * y result was promoted to int (not to unsigned int). That's why this diagnostic message was generated (unsigned long < int and so on)...

commented: Nice. I thought it was something like that, but couldn't find "chapter and verse". +21

>So there's a size mismatch.
And yet, the error doesn't say size mismatch, it says signed/unsigned mismatch. Your analysis is logical, but incorrect.

>why is it stated signed/unsigned mismatch when all
>variables are unsigned and no overflow is possible?
Because this is a case where the integral promotions can bite you. To summarize, both operands to the < operator are promoted using the integral promotion rules. i remains as is because its conversion rank is greater than int, so it continues to be an unsigned type. However, the result of x * y (unsigned short) has a conversion rank less than int, so that value is promoted to a type of int, which is signed.

[edit: Darnit, I hate getting interrupted while posting]

commented: Interesting. Wasn't aware that conversion rank was involved, though I suppose it makes sense in retrospect. +6

Compile this code with MSVC2005

unsigned short x = 20;
	unsigned short y = 20;

	for ( unsigned long i = 0; i < x * y ; i++ )
	{	
		cout<<i<<endl;
	}

and u get

warning C4018: '<' : signed/unsigned mismatch

why? i mean, it all runs fine, j is iterated till 400 and, as I know, the short unsigned should be converted in an unsigned long when doing the comparison, so no overflow cand be possible ... And, why is it stated signed/unsigned mismatch when all variables are unsigned and no overflow is possible?

thx in advance

I don't understand why you are using a unsigned long for your iterator, and shorts for what it compares to. Switch them all to one or the other (preferably short unless long is neccesary).

I think it's a very interesting question. From the C++ Standard (4.5, 1):

No doubts that VC++ int type can represent all the values of unsigned short. So x * y result was promoted to int (not to unsigned int). That's why this diagnostic message was generated (unsigned long < int and so on)...

Ok, but then, if I replace x with let's say... 65535 and y with 65535 the x*y would overflow int and the result would be a negative value... Now that's a problem. I tried it... the expected result was that the for would get iterated 0 times... but surprisingly... it worked, it iterated till 4294836225, wich is ofc unsigned int :| . So... i still don't get it

It's so simple to solve your problem (if you can't follow skatamatic's advice):

for ( unsigned long i = 0; i < (unsigned long)x * (unsigned long)y ; i++ )

It's so simple to solve your problem (if you can't follow skatamatic's advice):

for ( unsigned long i = 0; i < (unsigned long)x * (unsigned long)y ; i++ )

yes, I understand this is the way of solving the warning, but I'm still curious why if the implicit conversion is done from unsigned short to int the overflow doesn't occur. I mean if x = y =65535, then 65535*65535 = 4294836225 witch should be -131071 represented in int (4 bytes on my machine)=> the for should not loop at all. BUT IT DOES :)

the only logical explanation I can think of is that the conversion is done at runtime... The result of x*y overflows int, so it's converted to unsigned int.

It's not only the way of solving the compile-time warning problem, it's the way of solving right (run-time) calculations problem.
If we have unsigned long i and unsigned short x = 0xFFFFu and unsigned short y = 0xFFFFu then i < x * y computations are:
1. Do integral promotions for both multiplication operands (unsigned short to int)
2. Multiply int to int (int result 0xFFFE0001, integer overflow ignored in VC++)
3. Do int to long promotion of 0xFFFE0001 (do nothing in 32-bit VC++) then long to unsigned long conversion (the same 0xFFFE0001u but positive now; do nothing in 32-bit VC++).
4. Compare i with positive 0xFFFE0001.
Strictly speaking we have an unportable code: some C++ implementation may diagnose integer overflow in step #2! So explicit cast of x and y is the way to do this code portable.

It's not only the way of solving the compile-time warning problem, it's the way of solving right (run-time) calculations problem.
If we have unsigned long i and unsigned short x = 0xFFFFu and unsigned short y = 0xFFFFu then i < x * y computations are:
1. Do integral promotions for both multiplication operands (unsigned short to int)
2. Multiply int to int (int result 0xFFFE0001, integer overflow ignored in VC++)
3. Do int to long promotion of 0xFFFE0001 (do nothing in 32-bit VC++) then long to unsigned long conversion (the same 0xFFFE0001u but positive now; do nothing in 32-bit VC++).
4. Compare i with positive 0xFFFE0001.
Strictly speaking we have an unportable code: some C++ implementation may diagnose integer overflow in step #2! So explicit cast of x and y is the way to do this code portable.

ok, thx :) . It works in msvc 2005 too. I mean the conversion in step 2 is done here too. Anyway.. soved problem... thx

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.