#c #macros
#c #макросы
Вопрос:
Как написать FORMAT_OF(type)
, чтобы это было %d
для int
, %s
для и т.д. char *
Есть ли макрос для получения формата для базовых типов данных?
Комментарии:
1. Чего именно вы пытаетесь достичь? Вы должны знать типы данных объектов в вашей программе…
2. @sarnold , в моем случае
type
это также определяется макросом.3. До C1X вам придется писать макросы, которые принимают a
fmt
вместе с переменной.4. @Chris Lutz , что ты имеешь в виду? Можете ли вы опубликовать это в качестве ответа? Я могу согласиться с этим, поскольку я не могу принять еще не поддерживаемое решение c1x …
5. @new_perl — В принципе, вместо
PRINT(x) printf(FORMAT_OF(x), (x))
того, чтобы писатьPRINT(fmt, x) printf(fmt, x)
. Это больше кода у вызывающего, но это то, с чем вы застряли до C1X. Сейчас это не очень полезно, но если вы опубликуете больше о том, что вы пытались сделать, я мог бы помочь вам больше.
Ответ №1:
ДА. Но он доступен только в C11.
#define FORMAT_OF(x) _Generic((x),
int: "%d",
unsigned: "%u",
const char *: "%s",
void *: "%p")
Для типов вместо значений вы могли бы попробовать _Generic((type) 0, ...
.
Ваш компилятор, вероятно, не поддерживает C11. В GCC 4.6 (но не 4.5!) включена некоторая поддержка C11 с -std=c1x
помощью or -std=gnu1x
, но я не думаю _Generic
, что она пока поддерживается.
Комментарии:
1. @ChrisLutz: Я прочитал статью, в которой утверждалось, что стандарт был принят с единодушной поддержкой в предпоследнем голосовании, что означает, что окончательное голосование пропущено. Я не могу вспомнить, где я читал статью, и я не смог найти информацию на странице рабочей группы. Я не думаю, что он еще опубликован как C11, но это будет.
2. Потрясающе. Теперь все, что нам нужно сделать, это подождать еще 10 лет, пока они не начнут писать новый черновик для компиляторов, чтобы поддерживать его… (Кроме того, разве это не должно быть просто
char *
вместоconst char *
? Или будет_Generic
знать, что мойchar str[] = "This";
должен соответствовать aconst char *
? Может_Generic
использоваться для различенияconst
типов и неconst
типов?)3.
_Generic
Макрос проверяет только совместимость типов, поэтомуconst char *
будет перехватывать оба. Учитывая, что C11 фактически делает необязательными некоторые из обязательных функций C99, а некоторые из новых функций сильно перекрываются с C 11, я с осторожным оптимизмом смотрю на получение поддержки C11 «относительно скоро», по крайней мере, в GCC и Clang. На мой взгляд, новые функции C11 кажутся намного проще в реализации, чем новые функции в C99.4. Отрадно видеть, что GCC уже поддерживает некоторые функции из C1X. Было бы просто приятно видеть, что современная поддержка C будет более распространенной, поскольку поддержка C99 распространена по всей карте и существует уже долгое время.
Ответ №2:
Нет. В настоящее время стандартизированные версии C не поддерживают самоанализ типа такого рода.
Комментарии:
1. C11 имеет
_Generic
выражение.
Ответ №3:
Ну, если вы хотите, чтобы макрос принимал только тип, вы могли бы:
#define FORMAT_int "%d"
#define FORMAT_char "%c"
...
#define FORMAT(x) FORMAT_##x
и использовать FORMAT(int)
позже; но
int i;
FORMAT(i);
не будет работать и FORMAT(char*)
тоже не будет работать.
Ответ №4:
В C нет встроенных макросов, но вы можете легко написать функцию-оболочку для достижения этой цели.
Комментарии:
1. Как вы могли бы написать функцию-оболочку без C ?
2. Как бы вы написали такую функцию (без использования C201X
_Generic
)?3. Вы могли бы сделать это с ограниченным диапазоном типов (например
float
, /double
/long double
), используяsizeof
или какой-либо другой трюк, но в целом это не сработает.4.
sizeof
? Это не покажет разницу между anint
и achar*
в большинстве систем!5. @Dave — Вот почему я сказал «с ограниченным набором типов». Среди прочего, это делает его непригодным для определения
printf
форматов.