C Функция, которая вычисляет общий размер аргументов

В настоящее время я рассчитываю вычислить общий размер аргументов, передаваемых в функцию, в байтах. Теоретически, можно просто написать sizeof(x) для каждого аргумента. Тем не менее, это огромная трата времени, если вы хотите сделать это для многих функций. Я пытаюсь определить объем пространства для аргументов, чтобы я мог выделить нужный объем памяти для хранения их всех и хранения (для различных функций, со смешанными типами).

Я собираюсь сделать выражение, которое может определить размер всех аргументов для невариантной функции, независимо от их имен и независимо от их количества (в пределах разумного я поддержу только около 64). аргументы пока). Это может быть функция, макрос препроцессора, я независим от реализации. Я также был бы заинтересован в обработке функций с переменными числами, но я уверен, что это невозможно, потому что к тому времени, когда вы используете функцию с переменными числами, вы теряете всю информацию о типах данных.

В настоящее время я нашел три подхода, которые могут быть искажены, чтобы позволить мне сделать это. Первый основан на концепциях Laurent Подсчет аргументов Денио . Теоретически, я могу использовать макрос для генерации заголовка функции и выполнить аналогичную сложную работу, чтобы получить количество аргументов и передать их в различные макросы, которые обрабатывают КАЖДЫЙ индивидуальный случай, когда имеется N аргументов. (См .: Гадкий). По сути, я бы просто использовал псевдонимы всех имен функций с помощью макроса, а затем использовал sizeof для каждого из них. Проблема в том, что мне нужно сделать макрос для КАЖДОЙ длины аргументов, которые я хочу представить. И я действительно не предпочел бы сделать 64 (или больше) вещей, чтобы сделать одну работу.

Второй подход состоит в том, чтобы попытаться следовать подходу «Лучшего вариационного» материала Бена Клемера . Я бы не использовал весь его подход, но я бы попытался сгенерировать структуру, представляющую сигнатуру функции в структуре. Затем я мог бы попытаться получить размер элементов структуры (или даже самой структуры, если бы все, что меня волновало, было консервативной оценкой пространства). Это имеет несколько проблем. Во-первых, он может работать только на C99-совместимых вещах (все еще проверяя это). Во-вторых, это приводит к созданию дополнительной структуры для каждой реализованной функции. Это не совсем проблема, но все же есть проблема в том, что его подход к созданию структуры заканчивается теми же именами, что и функция (поэтому вам все равно нужно обращаться к именам, чтобы использовать их). Я, вероятно, мог бы обойти это хотя.

Третий подход, который был бы возможен, был бы рекурсивным макросом, хотя я не уверен, насколько счастливым это делает компиляторы. Теоретически возможно рекурсивно вытолкнуть элементы из VA_ARGS , вызвав макрос в виде POPPER(arg, ...) POPPER(VA_ARGS) + sizeof(arg). Ясно, что потребуется правило остановки, когда VA_ARG пусто (и что-то, что поможет вам не попасться с плавающим знаком +), но вы поняли идею.

Любая из этих вещей позволит мне сделать это:

  1. Хорошие, гибкие способы распаковать VA_ARGS из макроса с переменным значением. Если есть способ проиндексировать его
  2. Хороший пример рекурсивного макроса, на который можно было бы полагаться при выполнении этого (а также его ограничения в отношении максимального числа аргументов, совместимости компилятора, соответствия стандартам и т. д.).
  3. Способ напрямую получить общий размер всех аргументов с помощью проверки функций другого типа. В GCC, похоже, есть некоторые сумасшедшие функции для создания функций. вызовы для переадресации вызовов, которые могут быть применимы, но они относятся к конкретному компилятору, плохо документированы и, по-видимому, не сообщают о размере блока памяти, который они выделяют. Они также сообщают тонны нерелевантной информации.
7 голосов | спросил Namey 2 J0000006Europe/Moscow 2011, 22:48:45

2 ответа


0

Вам нужен макрос FOREACH, который позволяет расширять другой макрос на каждый элемент списка переменных. Это работает путем определения вариантов для каждой интересующей длины списка:

#define _NUM_ARGS(X100, X99, X98, X97, X96, X95, X94, X93, X92, X91, X90, X89, X88, X87, X86, X85, X84, X83, X82, X81, X80, X79, X78, X77, X76, X75, X74, X73, X72, X71, X70, X69, X68, X67, X66, X65, X64, X63, X62, X61, X60, X59, X58, X57, X56, X55, X54, X53, X52, X51, X50, X49, X48, X47, X46, X45, X44, X43, X42, X41, X40, X39, X38, X37, X36, X35, X34, X33, X32, X31, X30, X29, X28, X27, X26, X25, X24, X23, X22, X21, X20, X19, X18, X17, X16, X15, X14, X13, X12, X11, X10, X9, X8, X7, X6, X5, X4, X3, X2, X1, N, ...)   N
#define NUM_ARGS(...) _NUM_ARGS(__VA_ARGS__, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
#define EXPAND(X)             X
#define FIRSTARG(X, ...)      (X)
#define RESTARGS(X, ...)      (__VA_ARGS__)
#define FOREACH(MACRO, LIST)  FOREACH_(NUM_ARGS LIST, MACRO, LIST)
#define FOREACH_(N, M, LIST)  FOREACH__(N, M, LIST)
#define FOREACH__(N, M, LIST) FOREACH_##N(M, LIST)
#define FOREACH_1(M, LIST)    M LIST
#define FOREACH_2(M, LIST)    EXPAND(M FIRSTARG LIST) FOREACH_1(M, RESTARGS LIST)
#define FOREACH_3(M, LIST)    EXPAND(M FIRSTARG LIST) FOREACH_2(M, RESTARGS LIST)
        :

Получив это, вы можете написать макрос, чтобы получить размер его аргумента, и объединить их в цепочку, чтобы добавить их:

#define SUM_SIZEOF(X)  +sizeof(X)
size_t size = FOREACH(SUM_SIZEOF, (int, int, double, float));
ответил Chris Dodd 3 J0000006Europe/Moscow 2011, 00:54:30
0

Итак, в конце я пришел к выводу, что он функционирует до 64 аргументов (или столько, сколько вы действительно хотите определить функции FOR и COUNT_ARGS, действительно). Итак, спасибо за помощь. Надеюсь, эти лакомые кусочки полезны для других - они представляют мое расположение некоторых замечательных идей, распространенных по сети.

Я сделал конструкцию FOR_EACH немного более общей, чтобы я мог использовать ее для других задач (например, умножения и т. д., просто меняя префиксы и постфиксы).


/* CONCATENATE from Gregory Pakosz
    Source: http://stackoverflow.com/questions/1872220/is-it-possible-to-iterate-over-arguments-in-variadic-macros
*/

#define CONCATENATE(arg1, arg2)   CONCATENATE1(arg1, arg2)
#define CONCATENATE1(arg1, arg2)  CONCATENATE2(arg1, arg2)
#define CONCATENATE2(arg1, arg2)  arg1##arg2

/*  ---------------------------------
    |    Variadic/Iteration Macros   | 
    ---------------------------------*/

/*****************************************************
 COUNT_ARGUMENTS Counts the number of args to a variadic function, up to 64 (renamed from PP_NARG)
 Description: P_NARG macro returns the number of arguments that have been passed to it.
 Author: Laurent Deniau
 Source: https://groups.google.com/group/comp.std.c/browse_thread/thread/77ee8c8f92e4a3fb?hl=en%29
 NOTE: This may not work reliably if the function receives zero args, depending on compiler
*******************************************************/

#define COUNT_ARGUMENTS(...) PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
#define PP_NARG_(...) PP_ARG_N(__VA_ARGS__)
#define PP_ARG_N( \
          _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
         _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
         _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
         _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
         _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
         _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
         _61,_62,_63,N,...) N
#define PP_RSEQ_N() \
         63,62,61,60,                   \
         59,58,57,56,55,54,53,52,51,50, \
         49,48,47,46,45,44,43,42,41,40, \
         39,38,37,36,35,34,33,32,31,30, \
         29,28,27,26,25,24,23,22,21,20, \
         19,18,17,16,15,14,13,12,11,10, \
         9,8,7,6,5,4,3,2,1,0


/*****************************************************
 FOR_EACH_COMPOSER Composition macro to create expressions where some sequence is bound by prefix  postfix
 Description: For each macro, but built more generally to allow expressing sums as well as series of functions.
 Adapted from: Gregory Pakosz
 Source: http://stackoverflow.com/questions/1872220/is-it-possible-to-iterate-over-arguments-in-variadic-macros
 Functional up to 64 arguments.
*******************************************************/

#define FOR_EACH_COMPOSER_1(prefix, postfix, finalPrefix, finalPostfix, x, ...) finalPrefix(x)finalPostfix
#define FOR_EACH_COMPOSER_2(prefix, postfix, finalPrefix, finalPostfix, x, ...)\
  prefix(x)postfix\
  FOR_EACH_COMPOSER_1(prefix, postfix, finalPrefix, finalPostfix, __VA_ARGS__)
#define FOR_EACH_COMPOSER_3(prefix, postfix, finalPrefix, finalPostfix, x, ...)\
  prefix(x)postfix\
  FOR_EACH_COMPOSER_2(prefix, postfix, finalPrefix, finalPostfix, __VA_ARGS__)

/* Etc, up to 64 */

#define FOR_EACH_COMPOSER_(N, prefix, postfix, finalPrefix, finalPostfix, ...) CONCATENATE(FOR_EACH_COMPOSER_, N)(prefix, postfix, finalPrefix, finalPostfix, __VA_ARGS__)

#define FOR_EACH_COMPOSER(prefix, postfix, finalPrefix, finalPostfix, ...) FOR_EACH_COMPOSER_(COUNT_ARGUMENTS(__VA_ARGS__), prefix, postfix, finalPrefix, finalPostfix, __VA_ARGS__)

/*****************************************************
 SIZE_OF_ARGUMENTS Calculates the size of the given arguments
 Description: For each argument, calculates the sizeof returns the sum
 Author: Benjamin Nye
 NOTE: This may not work reliably if the function receives zero args, depending on compiler
*******************************************************/
#define SIZE_OF_ARGS(...) FOR_EACH_COMPOSER(sizeof , +, sizeof , + 0, __VA_ARGS__)
ответил Namey 16 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowFri, 16 Sep 2011 19:44:55 +0400 2011, 19:44:55

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132