Я хочу напечатать значение переменной без указания его типа.
В c, я могу сделать
int main(int argc, char **argv) { int i = 1; float f = 0.1; char s[] = "s"; printf("%i\n", i); printf("%f\n", f); printf("%s", s); return 0; }
но я ожидаю:
int main(int argc, char **argv) { int i = 1; float f = 0.1; char s[] = "s"; printf("%any_type\n", i); printf("%any_type\n", f); printf("%any_type", s); return 0; }
вопрос: есть ли %any_type
в C?
В C11
вы можете написать общую функцию для печати любого типа и продолжать добавлять свой настраиваемый тип к этой функции.
#define print_any(X) _Generic((X), int: print_int, \ default: print_unknown, \ float: print_float)(X) int print_int(int i) { return printf("%d\n", i); } int print_float(float f) { return printf("%f\n", f); } int print_unknown(...) { return printf("ERROR: Unknown type\n"); }
Вы также можете автоматизировать генерацию функций, как показано ниже.
#define GEN_PRINT(TYPE, SPECIFIER_STR) int print_##TYPE(TYPE x) { return printf(SPECIFIER_STR "\n", x);} GEN_PRINT(int, "%d"); GEN_PRINT(char, "%c"); GEN_PRINT(float, "%f");
Использование будет:
int main(int argc, char **argv) { int i = 1; float f = 0.1; char s[] = "s"; print_any(i); print_any(f); print_any(s); return 0; }
Нет, вам нужно указать правильный спецификатор формата.
В C11 вы можете автоматизировать вычисление правильного спецификатора формата с помощью _Generic
сочетании с макросом. Однако вам нужно повторить имя переменной (один раз для вычисления спецификатора и один раз, чтобы указать переменную как аргумент).
Для более подробной информации прочитайте эту ссылку .
Нет, printf
– это так называемая вариационная функция , что означает, что он может принимать любые числа / типы параметров.
Проблема (ну, одна из них) с вариационными функциями в classическом C состоит в том, что параметры не являются безопасными типами, то есть – вызываемая функция не имеет представления о типе параметров.
Вот почему переменные набираются с использованием строки формата для начала, printf не имеет представления о том, является ли переданное значение указателем, целочисленным или каким-либо другим типом, и нужно посмотреть строку формата, чтобы выяснить, в каком формате отображать Значение.
Это, к сожалению, также открывает возможность ошибок, если строка формата неверна, например, говоря, что значение является указателем на что-то, когда оно действительно является целым числом, программа может сбой (а точнее, вызвать неопределенное поведение) от попытки получить доступ к значению не указателя в качестве указателя.
Таких вещей нет. Мы должны сказать, в каком формате мы собираемся напечатать это значение.