Search code examples
ctype-conversionimplicit-conversion

How to avoid the (potential) error by conversion when assigning a char to a char with ternary operator


I have the following Code:

void foo(char* char_ptr, unsigned short len) {
    char c = len != 0 ? char_ptr[0] : '\0';
    printf("%c", c);
}

I get the following warning:

Clang-Tidy: Narrowing conversion from 'int' to signed type 'char' is implementation-defined

What conversion is this thing talking about? I have only chars everywhere. How can I avoid this (potential) error? This looks like another case of "There's some implicit magic going on that you just have to know about". Is there a place where I can lookup all the magic that the c-compiler is implicitly doing?


Solution

  • Interpreting the information from this cppreference page, specifically in the "Conditional Operator" section, subsections (3) and (1), we see:

    (3) Performs a conversion from the result of the evaluation to the common type, defined as follows:

    (1) if the expressions have arithmetic type, the common type is the type after usual arithmetic conversions

    Then, looking at the linked "usual arithmetic conversions", we see:

    (4) Otherwise, both operands are integers. Both operands undergo integer promotions (see below); then, ...

    Those integer promotions will cause both expressions to be promoted to int types - even if you explicitly cast the second, as in char c = len != 0 ? char_ptr[0] : (char)'\0';.

    So, in order to silence the warning, the result of the conditional expression (which will be of int type) needs to be cast to a char, as in:

        char c = (char)(len != 0 ? char_ptr[0] : '\0');
    

    From this Draft C11 Standard

    6.5.15 Conditional Operator
    ...
    5 If both the second and third operands have arithmetic type, the result type that would be determined by the usual arithmetic conversions, were they applied to those two operands, is the type of the result.

    Which appears to confirm the information presented by cppreference.com.