I encountered some unexpected results when porting some older code involving the way armcc appears to handle types. Note that uint16_t is an "unsigned short".
In compilers I'm familiar with, if you do the following:
uint16_t x = 0x0001
uint16_t y = 0x0002
then the following IF statement will be evaluated as true:
if((x-y) > 0x8000)
This is because the subtraction of 2 uint16_t variables returns a uint16_t result of 0xFFFF.
When compiling and running the test code below with armcc:
uint16_t x; uint16_t y; uint16_t z1[2]; bool result[8]; x = 0x0001; y = 0x0002; z1[0] = x - y; z1[1] = (uint16_t)(x - y); if((x-y) > 0x8000) result[0] = 1; if((uint16_t)(x-y) > 0x8000) result[1] = 1; if((x-y) > (uint16_t)(0x8000)) result[2] = 1; if((uint16_t)(x-y) > (uint16_t)(0x8000)) result[3] = 1; if(z1[0] > 0x8000) result[4] = 1; if((uint16_t)(z1[0]) > 0x8000) result[5] = 1; if(z1[0] > (uint16_t)(0x8000)) result[6] = 1; if((uint16_t)(z1[0]) > (uint16_t)(0x8000)) result[7] = 1;
I get the following results:
z1[0] is 0xFFFF
result[0] is 0
result[1] is 1
result[2] is 0
result[3] is 1
result[4] is 1
result[5] is 1
result[6] is 1
result[7] is 1
Why do I have to typecast the result of subtracting two uint16_t variables as uint16_t for the if statement to evaluate as true? Is there some place in the armcc documentation that explains how the compiler handles these evaluations (promotions, automatic typecasting, etc)?
Brandon Price said:Why do I have to typecast the result of subtracting two uint16_t variables as uint16_t for the if statement to evaluate as true?
Because you're no longer on a 16-bit CPU.
Does that mean that doing math operations to uint16_t will always result in a uint32_t? Is there some way to learn how armcc will handle these kinds of operations? I looked through the user guide ( https://developer.arm.com/documentation/dui0472/m/compiler-features ) but didn't find anything addressing this topic.
Brandon Price said:Does that mean that doing math operations to uint16_t will always result in a uint32_t?
No. It results in a value of type int. It's signed, which is why your comparison failed.
This does not concern specifics of the ARM C compiler --- it's a general property of the C programming language. C never does arithmetic on any integer type smaller than int (signed or unsigned). On a 32-bit machine those are 32-bit data types. The exact rules are a bit too complicated to lay out here. You should really consult your C textbooks.
Thanks so much, I'll look into this further!
I think this is the relevant source material explaining how the implicit typecasting / promotion rules for C: https://en.cppreference.com/w/c/language/conversion#Usual_arithmetic_conversions