Задать вопрос
@seityaya

Почему при перегрузке функции через макрос, появляются предупреждение в _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
  • Вопрос задан
  • 304 просмотра
Подписаться 2 Сложный Комментировать
Помогут разобраться в теме Все курсы
  • Нетология
    Разработчик на C++
    12 месяцев
    Далее
  • Яндекс Практикум
    Разработчик C++
    9 месяцев
    Далее
  • Яндекс Практикум
    Разработчик C++ расширенный
    12 месяцев
    Далее
Решения вопроса 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))
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

Похожие вопросы
АО НПП «АМЭ» Санкт-Петербург
До 250 000 ₽
Uniscan Research Новосибирск
от 140 000 до 200 000 ₽
Базис-Центр Коломна
от 70 000 до 500 000 ₽