Search code examples
ctypesmisra

Return types of operator == in C


What is the return type of any operator ? How to determine it?
Is it platform dependent ?

This question popped up while I was doing MISRA code compliance for as I was
required to typecast the parameters of the if keyword like this

if((bool_t)(cmd <= 1)){} 

to appease lint of the 14.4 MISRA required guideline. can you point me to some documentation regarding operator return type ?
If anyone can find out the documentation for the return types of the
operators please post it here as it will be of great help for people
referring hereafter.


Solution

  • Return types of operator == in C

    ... The result has type int. ... C11dr Equality operators §6.5.9 3

    What is the return type of any operator ?

    Sometimes it depend on the operator and the operands

    a*b --> result type could be `int`, `double`, etc.
    

    Others, it is fixed.

    a==b --> result type is `int`.
    

    How to determine it?

    1. By code analysis - you or a static analyzer looks at the code.

    2. At run time, use _Generic()

    The following handles many situations.

    #define typenameX(X) _Generic((X), \
    _Bool: "_Bool", \
    signed char: "signed char", \
    char: "char", \
    unsigned char: "unsigned char", \
    short: "short", \
    unsigned short: "unsigned short", \
    int: "int", \
    unsigned: "unsigned", \
    long: "long", \
    unsigned long: "unsigned long", \
    long long: "long long", \
    unsigned long long: "unsigned long long", \
    float: "float", \
    double: "double", \
    long double: "long double", \
    _Complex float: "_Complex float", \
    _Complex double: "_Complex double", \
    _Complex long double: "_Complex long double", \
    void *: "void *", \
    char *: "char *", \
    const char *: "const char *", \
    default: "other" \
    )
    
    int main(void) {
      double a = 2.0;
      puts(typenameX(a));
      puts(typenameX(a==4.0));
      short b;
      puts(typenameX(b));
      puts(typenameX(b*1));
      puts(typenameX(sizeof(b)));
      double cmd;
      puts(typenameX(cmd <= 1));
    }
    

    Output

    double
    int
    short
    int
    unsigned long
    int
    

    Is it platform dependent ?

    With cmd <= 1, the return type in C is int - "platform independent".

    The result type of ((int)i) * 123456 is "platform dependent". It could be int or long for example.

    can you point me to some documentation regarding operator return type ?

    In the case of if((bool_t)(cmd <= 1)){}, the result type of cmd <= 1 is int. C11 §6.5.8 6. The bool_t is not needed when compiling in C. Since the result type may differ in other languages (or with a non-compliant C compiler), code that needs to compile in more than one language may benefit by the cast.

    The best document regarding operator return type is the (latest) C spec.


    The concerns about "required to typecast the parameters of the if keyword" comes into play in arcane situations. The result of a compare in C is not one of them.

    C well defines the result of if(expression) to be "if the expression compares unequal to 0.". C11dr §6.8.4.1 2

    A non-compliant compiler may convert floating-point or a wide integer to an int first and then test against zero. if((bool_t)x) fixes that.

    unsigned long long w = 0x800000000000u;
    if (w) {
    
    double x = 4294967296.0; // 0x1 0000 0000
    if (x) {
    
    double y = 0.123;
    if (y) {
    

    Handling of NaN is problematic. OTOH, C does not well define how NaN compares to 0. IEEE 758 does well define it and many C implementations follow that. I do not see casting to (bool_t) helps in this case as it is equally lose concerning NaN.

    double z = 0.0/0.0; // z is NaN;
    if (z) {
    
    if (!z) {
    

    In early C++, there was no boolean either. A user defined object, (but not double, float, pointers), was converted to int for the if(). An arithmetic class (e.g. effecting a 256 integer) would have trouble should a non-zero value convert to int 0. Using !! solved that.

    myint256 a = foo();
    if (!!a) {
    

    Note: If a compiler does not have a true boolean type, then (bool_t) being maybe some integer type, will certainly foul code, much like above.