Почему при перегрузке функции через макрос, появляются предупреждение в _Generic на каст?

Есть код, в котором происходит перегрузка функции через макрос.

Компилятор выдаёт предупреждение на каст переменных, но скомпилированная программа работает правильно.
Подавление предупреждений не вариант.

Хотелось бы знать причину предупреждений, это стандартное поведение или несовершенство препроцессора?

Минимальный код для проверки и экспериментов.

#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
 
#define FNK(...) \
        FFF_x(, \
                ##__VA_ARGS__, \
                FFF_B(__VA_ARGS__), \
                FFF_A(__VA_ARGS__), \
                FFF_0(__VA_ARGS__))
 
#define FFF_x(x, A, B, FFF, ...)FFF
 
#define FFF_0() fnk(0, 0, NULL)
#define FFF_A(A) fnk(A, 0, NULL)
 
#define FFF_B(A, BC) \
        _Generic((A), \
                int : _Generic((BC), \
                        int : fnk(A, BC, NULL), \
                        char * : fnk(A, 0, BC)))
 
void fnk(uintmax_t A, uintmax_t B, char* C){
    printf("A : %"PRIXMAX"\n", A);
    printf("B : %"PRIXMAX"\n", B);
    printf("C : \"%s\"\n", C);
}
 
void fnk_test(void){
    printf("\n0)---------\n");
    FNK();
 
    printf("\n1)---------\n");
    FNK(1);
 
    printf("\n2.1)---------\n");
    FNK(1, 2);
 
    printf("\n2.2)---------\n");
    FNK(1, "2");
}
 
int main() {
    fnk_test();
    return 0;
}


В FNK(1, 2); -- ругается на то, что переменная не char *

в FNK(1, "2"); -- наоборот, что не int.

Вывод программы:
0)---------
A : 0
B : 0
C : "(null)"
 
1)---------
A : 1
B : 0
C : "(null)"
 
2.1)---------
A : 1
B : 2
C : "(null)"
 
2.2)---------
A : 1
B : 0
C : "2"

Предупреждения:
5f1a02eb5bb9f426989446.png
  • Вопрос задан
  • 285 просмотров
Решения вопроса 1
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
Хотелось бы знать причину предупреждений, это стандартное поведение или несовершенство препроцессора?

Препроцессор-то тут ни при чём. Если посмотреть в
препроцессированный код,

_Generic((1), int : _Generic((2), int : fnk(1, 2,
# 37 "generic.c" 3 4
   ((void *)0)
# 37 "generic.c"
   ), char * : fnk(1, 0, 2)));

    printf("\n2.2)---------\n");
    _Generic((1), int : _Generic(("2"), int : fnk(1, "2",
# 40 "generic.c" 3 4
   ((void *)0)
# 40 "generic.c"
   ), char * : fnk(1, 0, "2")));

то видно, что выражение выбираемое _Generic имеет правильные типы, но выражения в других ветках при этом имеют неправильные типы. Предупреждение об этом.

Пофиксить можно было бы заведя две разные функции для int и char * и выбирая в _Generic только нужную функцию, а не всё выражение. Типа того:

void fnk_int(uintmax_t A, uintmax_t B){
...
}
void fnk_pchar(uintmax_t A, char *B){
...
}

#define FFF_B(A, BC) \
        _Generic((A), \
                int : _Generic((BC), \
                        int : fnk_int, \
                        char * : fnk_pchar)(A, BC))
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы