C11_Generic prints true and false as integers

C11 has a _Generic macro that can allow the use of cool common functions. However, using true and false with this leads to incorrect deduction in the normal case:

 #include <stdio.h> #include <stdbool.h> #define TypeName(x) \ _Generic((x), \ bool: "bool", \ int: "int", \ default: "unknown") #if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && (__bool_true_false_are_defined) # undef true # define true ((bool)(1)) # undef false # define false ((bool)(0)) #endif int main(void) { printf("1: %s\n", TypeName(1)); printf("true: %s\n", TypeName(true)); printf("false: %s\n", TypeName(false)); } 

Fingerprints:

 1: int true: bool false: bool 

However, without the middle bit, which overrides true and false :

 1: int true: int false: int 

This means that you cannot execute _Generic functions, such as:

 struct Variant * const int32 = variant_create(1); struct Variant * const boolean = variant_create(true); 

So my questions are :

  • Is redefinition fragment safe?
  • Is it C11 oversight or a bug in GCC and Clang?
+6
source share
4 answers

Both types are really macros:

7.18 Boolean type and values

  1. The remaining three macros are suitable for use in #if directives for preprocessing.
    They:
    true, which expands to an integer constant 1,
    false, which expands to the integer constant 0,
    and
    __bool_true_false_are_defined, which expands to an integer constant 1.

The last rule says that you are allowed to override the macro:

  1. Notwithstanding the provisions of clause 7.1.3, the program may determine and, possibly, then override the macros bool, true and false. 259)

    259) See “Future Directions of the Library (7.31.9)

despite the above rule:

7.1.3 Reserved Identifiers

  1. If the program deletes (C # undef) any macro identifier definition in the first group, the above is undefined behavior.

Rule 7.31.9 says redefinition may not be a good idea:

7.31.9 Boolean type and values

  • The ability to defragment and possibly override macros bool, true and false is an obsolete feature.

So, I suggest you create your own macros my_true and my_false, which are passed to _Bool.

+8
source

This is because true and false in stdbool.h are integers 1 and 0 , their types are really int , not bool .

C11 §7.18 Boolean type and values <stdbool.h>

The other three macros are suitable for use in #if preprocessing directives. They are

 true 

which expands to an integer constant 1 ,

 false 

which expands to the integer constant 0 and

 __bool_true_false_are_defined 

which expands to an integer constant 1 .

+4
source

C has no literals for integer types that are narrower than int , and as others have said, the macros false and true therefore defined as 0 and 1 respectively. Thus, the problem that you describe for _Bool is the same for all other narrow data types: it is difficult to call, for example, the short variant in the universal type wizard, and calling such a macro with 'A' will not result in char .

Your replacement macros are not suitable, because they cannot be used in #if preprocessor expressions. If some code that you include later uses them, because such a compilation will fail.

you can use

 # define true ((_Bool)+1) # define false ((_Bool)+0) 

instead of this. The small plus + signifies that the preprocessor interprets them as ((0)+1) and ((0)+0) in the expressions, and therefore they will still do what you expect.

+2
source

The answer to your question is “Is this a supervision in the C11 standard or a mistake in GCC and Clang?” no.

Others explained why this is not a bug in GCC and Clang.

Nor is it an oversight in the standard that defines true and false in this way for backward compatibility. If true were defined as (bool) 1 and false as (bool) 0, then most likely they will encounter incompatible macro definitions. The most noticeable effect will be a warning. Compilers do not warn at all if redefining a macro (without #undef intervention) does not change the definition; therefore, the simplest definition is least likely to give problems in the wild.

0
source

Source: https://habr.com/ru/post/980758/


All Articles