我试图创建一个伪超级结构来打印结构数组.我的基本结构如下.
/* Type 10 Count */ typedef struct _T10CNT { int _cnt[20]; } T10CNT; ... /* Type 20 Count */ typedef struct _T20CNT { long _cnt[20]; } T20CNT; ...
我创建了下面的结构来打印上面提到的结构数组.编译下面的代码片段时,我解除了引用void指针错误.
typedef struct _CMNCNT { long _cnt[3]; } CMNCNT; static int printCommonStatistics(void *cmncntin, int cmncnt_nelem, int cmncnt_elmsize) { int ii; for(ii=0; ii_cnt[0]); fprintf(stout,"STATISTICS_OUT: %d\n",cmncnt->_cnt[1]); fprintf(stout,"STATISTICS_ERR: %d\n",cmncnt->_cnt[2]); } return SUCCESS; } T10CNT struct_array[10]; ... printCommonStatistics(struct_array, NELEM(struct_array), sizeof(struct_array[0]); ...
我的目的是有一个共同的功能来打印所有数组.请让我知道使用它的正确方法.
提前感谢您的帮助.
编辑:参数名称从cmncnt更改为cmncntin.对不起,这是错误的错误.
谢谢,Mathew Liju
我认为你的设计会失败,但我也不相信我看到的其他答案完全处理了更深层次的原因.
看起来你正在尝试使用C来处理泛型类型,这些东西总是变得毛茸茸.你可以做到,如果你小心,但这并不容易,在这种情况下,我怀疑它是否值得.
更深层次的原因:让我们假设我们已经超越了单纯的句法(或者仅仅是句法)问题.您的代码显示T10CNT包含20,int
而T20CNT包含20 long
.在现代的64位机器上 - 除了Win64之外 - sizeof(long) != sizeof(int)
.因此,打印函数中的代码应该区分解除引用int
数组和long
数组.在C++中,有一个规则,你不应该尝试多态地处理数组,这就是为什么.CMNCNT类型包含3个long
值; 尽管阵列的基本类型与T20CNT匹配,但数量上与T10CNT和T20CNT结构不同.
风格建议:我强烈建议避免在名称上引入下划线.通常,以下划线开头的名称保留供实现使用,并用作宏.宏不尊重范围; 如果实现定义了一个宏_cnt,它会破坏你的代码.保留名称有细微差别; 我不打算进入那些细微差别.认为"以下划线开头的名字是保留的"会更简单,它会引导你避免麻烦.
样式建议:您的打印功能无条件地返回成功.那是不明智的; 你的函数应该什么都不返回,这样调用者就不必测试成功或失败(因为它永远不会失败).注意到函数返回状态的仔细编码器将始终测试返回状态,并具有错误处理代码.该代码永远不会执行,因此它已经死了,但任何人(或编译器)都很难确定.
表面修复:暂时,我们可以假设您可以将int
其long
视为同义词; 但是你必须习惯于认为它们是同义词.该void *
参数是说"这一函数的不确定类型的指针"的正确方法.但是,在函数内部,您需要void *
在进行索引之前从a转换为特定类型.
typedef struct _CMNCNT { long count[3]; } CMNCNT; static void printCommonStatistics(const void *data, size_t nelem, size_t elemsize) { int i; for (i = 0; i < nelem; i++) { const CMNCNT *cmncnt = (const CMNCNT *)((const char *)data + (i * elemsize)); fprintf(stdout,"STATISTICS_INP: %ld\n", cmncnt->count[0]); fprintf(stdout,"STATISTICS_OUT: %ld\n", cmncnt->count[1]); fprintf(stdout,"STATISTICS_ERR: %ld\n", cmncnt->count[2]); } }
(我也喜欢调用文件流的想法stout
. 建议:在真正的源代码上使用cut'n'paste - 它更安全!我通常使用" sed 's/^/ /' file.c
"为cut'n'paste准备代码到SO答案.)
那条演员阵线做了什么?我很高兴你问...
第一个操作是转换const void *
为const char *
; 这允许您对地址执行字节大小操作.在标准C之前的日子里,char *
被用来代替void *
通用寻址机制.
下一个操作添加正确的字节数,以获取i
size对象数组的th元素的开头elemsize
.
然后第二个演员告诉编译器"相信我 - 我知道我在做什么"并"将此地址视为CMNCNT结构的地址".
从那里,代码很容易.请注意,由于CMNCNT结构包含long
值,我过去常常%ld
说实话fprintf()
.
由于您不打算修改此函数中的数据,因此const
像我一样使用限定符并不是一个坏主意.
请注意,如果您要忠实于此sizeof(long) != sizeof(int)
,那么您需要两个单独的代码块(我建议使用单独的函数)来处理'数组int
'和'数组long
'结构类型.