C函数计算参数的总大小
我目前正在计算传入函数的参数的总大小(以字节为单位)。 理论上,每个参数都可以写出sizeof(x)
。 但是,如果想为许多功能做这件事,这是一个巨大的浪费时间。 我试图找出参数的空间量,以便我可以分配适量的内存来存储它们并存储它们(对于具有混合类型的各种函数)。
我正在寻找一个表达式,它可以确定所有参数的大小,而不管它们的名称是什么,并且不管它们有多少(理由是,我很好,现在只支持大约64个参数)。 它可以是一个函数,一个预处理器宏,我对实现不可知。 我也会对处理可变参数函数感兴趣,但我很确定这是不可能的,因为当你进入可变参数函数时,你已经失去了关于数据类型的所有信息。
目前,我发现有三种方法可能会让我这样做。 第一个是基于Laurent Deniau的arg counting的概念。 理论上,我可以使用一个宏来生成函数头,并且执行一些类似的花式步骤来获取参数的数量并派发到处理每个有N个参数的每个个案的各种宏。 (见:丑)。 基本上,我只是使用宏对所有函数名称进行别名,然后在其中的每一个上使用sizeof。 问题是,我需要为每个我想表示的参数创建一个宏。 而且我真的不想让64个(或更多)的东西去完成一项工作。
第二种方法是尝试遵循本·克莱默的“更好的可变参数”的方法。 我不会使用他所有的方法,但我会尝试生成一个结构体,它将一个函数的参数签名表示为结构体。 然后,我可以尝试获取结构元素的大小(或者甚至是结构本身,如果我关心的是对空间的保守估计)。 这有几个问题。 首先,它可能只适用于C99兼容的东西(仍在检查)。 其次,它导致为每个实现的功能创建一个额外的结构。 这并不完全是一个问题,但它仍然存在一个问题,即他构造一个结构的方法最终会使用与函数相同的名称(因此您仍然需要引用名称来使用它们)。 不过我可以解决这个问题。
第三种方法可能是递归宏,尽管我不确定编译器有多快乐。 理论上可以通过以POPPER(arg, ...) POPPER( VA_ARGS ) + sizeof(arg)
的形式调用一个宏来从VA_ARGS递归地弹出元素。 很显然,当VA_ARG为空时(以及确保不会被浮动+符号捕获),它需要一个暂停规则,但你明白了。
任何一件事情都可以让我做到这一点:
您需要一个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)
:
一旦你有了,你可以编写一个宏来获得它的arg的大小,并将它们链接在一起来添加它们:
#define SUM_SIZEOF(X) +sizeof(X)
size_t size = FOREACH(SUM_SIZEOF, (int, int, double, float));
所以这就是我最终想到的,它最多可以运行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__)
链接地址: http://www.djcxy.com/p/52877.html
上一篇: C Function that calculates total sizeof arguments
下一篇: Extension methods defined on value types cannot be used to create delegates