cvariablesiar

IAR for AVR compiler - converting unsigned short to unsigned char without warning


today I've catched quite unfamiliar situation with my code. I've changed type of variable passed as parameter to function - from unsigned char to unsigned short and...there was no warning! On the debug I saw that variable's value is truncated and rest of the functio happily play with half of value without any problem....what the heck?!

Below short code snippet:

void func1(unsigned char param)
{
    if(param == 0x02) //even if passed parameter is 0x0102, truncated data fits and enter branch
    {
        __asm("nop"); //just anything to avoid optimization
    }  
}

void func2(void)
{
    unsigned short param_test = 0x0102;
    unsigned char test2;

    test2 = param_test; //completely fine for compiler, "test2" stores 0x02 value
    (void)test2;        //to avoid compiler warning of not used variable

    func1(param_test);
}

IAR compiler doesn't see any problem to not inform programmer that something may not work as intended...

Windows C compiler is VS at least return warning C4244: "conversion from unsigned short to unsigned char, possible loss of data". Is there any flag for IAR as well? I couldn't find it yet...


Solution

  • From the Annex I of the ISO/IEC 9899:1999 C Language Specification:

    An implementation may generate warnings in many situations, none of which are specified as part of this International Standard. The following are a few of the more common situations. [...]

    • An implicit narrowing conversion is encountered, such as the assignment of a long int or a double to an int, or a pointer to void to a pointer to any type other than a character type (6.3).

    [...]

    Meaning that, according to the standard, the char type is not "generally" entitled for warning.

    One potential solution, based on this particular question, is to pass the parameter as a pointer in the func1() function:

    #include <stdbool.h>
    
    bool func1(unsigned char *param);
    bool func1(unsigned char *param)
    {
        return (*param == 0x02);
    }
    

    Under such situation, the compiler will generate a compile time error when trying to pass a pointer to a short:

    func1(&param_test); 
    

    will fail with Error[Pe167]: argument of type "unsigned short *" is incompatible with parameter of "unsigned char *".

    In general, such practice can help to catch bugs at compile time with a potentially good side effect of saving some cycles.