Joshua Ryan
Joshua Ryan

Reputation: 648

Is printing an enum without a cast okay in C++?

#include <stdio.h> 

enum class TEST_ENUM{
    VALUE =1,
};

int main( ){
    // Gcc will warn. 
    printf("%u", TEST_ENUM::VALUE);

    // Both clang and gcc are happy. 
    printf("%u", uint32_T(TEST_ENUM::VALUE));
}

Godbolt link

In the above example, gcc will emit the following diagnostic:

<source>:8:12: warning: format '%u' expects argument of type 'unsigned int', but argument 2 has type 'TEST_ENUM' [-Wformat=]

     printf("%u", TEST_ENUM::VALUE);

Regardless of compiler version or warnings enabled, I cannot seem to get clang to emit that same diagnostic. Since this is a warnning and not an error, I assume both are standards compliant. Why does gcc complain when clang won't? Is gcc being overly cautious here, or is there actually something worth warning about?

Upvotes: 0

Views: 324

Answers (1)

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 122585

From cppreference:

... - arguments specifying data to print. If any argument after default conversions is not the type expected by the corresponding conversion specifier, or if there are fewer arguments than required by format, the behavior is undefined. If there are more arguments than required by format, the extraneous arguments are evaluated and ignored

Is gcc being overly cautious here, or is there actually something worth warning about?

Not at all overly cautios. You are passing a parameter of wrong type!

Since this is a warnning and not an error, I assume both are standards compliant. Why does gcc complain when clang won't?

When your code has undefined behavior then compilers are not required to issue any diagnostics. GCC is just being nice to you here.

If you are forced to use a type-unsafe API you can always wrap it into something type-safe :

void Log(const TEST_ENUM& x) {
    the_actual_logging_api( "%u", static_cast<std:underlying_type<TEST_ENUM>>(x));   
}

Upvotes: 3

Related Questions