Search code examples
cenumsreturn-valuec89ansi-c

returning enum as char doesn't actually return the value of that enum


I have an enum:

enum asm_adressing_types{instant = 0, direct = 1, relative = 2, instant_register = 3}; 

and I am returning values of the enum using the following function:

char addressing_type(char *operand)
{
    switch (*operand)
    {
        case DIRECT_REGISTER_ADRESSING_START_SYMBOL:
            return (char)(instant_register); /*<- This line get executed. (checked via debugger)*/
         break;
        case INSTANT_ADRESSING_START_SYMBOL:
            return (char)(instant);
         break;
         case RELATIVE_ADRESSING_START_SYMBOL:
            if(!is_register(operand))
                return (char)(direct);
            return (char)(relative);
         break;
        default:
          return (char)(direct);
    }
}

When I am trying to return 3 (instant_register) The value that is practically returned is 1:

if((commands + i)->operands.first_free_index >= 1 && (temp.command_byte_form.desttype = addressing_type(get_item_at_index((commands + i)->operands, 0)) == instant_register))
/*value of temp.command_byte_form.desttype after this line of code is 1 (checked via debugger)*/

Why that is? And how can I make the function return the actual value of the enum?

edit: : desttype is a 2 bit unsigned int bitfield


Solution

  • The issue is not caused by the return value, the castings or the enumeration constants of asm_adressing_types, which do work perfectly.

    It has to be caused by a match failure in the switch condition inside of the addressing_type function.

    The pointer parameter operand is high-probably pointing to a value which does not match to the value of the DIRECT_REGISTER_ADRESSING_START_SYMBOL ,INSTANT_ADRESSING_START_SYMBOL and optionally also not the RELATIVE_ADRESSING_START_SYMBOL symbols at the first, second and third case.

    Thus the result is printing 1, the value of the direct enumeration constant, which is returned at the third (when is_register(operand) returned 0) or default case.

    Here is the proof that it works properly, when f.e. DIRECT_REGISTER_ADRESSING_START_SYMBOL matches *operand:

    Online

    #include <stdio.h>
    
    enum asm_adressing_types { instant = 0, direct = 1, relative = 2, instant_register = 3 }; 
    enum symbols { DIRECT_REGISTER_ADRESSING_START_SYMBOL = 'A', INSTANT_ADRESSING_START_SYMBOL = 'B', RELATIVE_ADRESSING_START_SYMBOL = 'C' };
    
    char addressing_type (char *operand);
    
    int main (void)
    {
        char a = 'A';
        char *p = &a;
        printf("%d", addressing_type(p));
    }
    
    char addressing_type (char *operand)
    {
        switch (*operand)
        {
            case DIRECT_REGISTER_ADRESSING_START_SYMBOL:
                return (char)(instant_register); /*<- This line get executed. (checked via debugger)*/
                break;
            case INSTANT_ADRESSING_START_SYMBOL:
                return (char)(instant);
                break;
            case RELATIVE_ADRESSING_START_SYMBOL:
                if (1)                           // simplification for the sake of the experiment.
                    return (char)(direct);
                return (char)(relative);
                break;
            default:
                return (char)(direct);
                break;
        }
    }
    

    Output:

    3
    

    Note that the casting and the surrounding parentheses for the enumerations constants is redundant. You can just use:

    return instant_register;