当前位置:  开发笔记 > 程序员 > 正文

在C中的struct中"解除引用`void*'指针"警告的解决方案?

如何解决《在C中的struct中"解除引用`void*'指针"警告的解决方案?》经验,为你挑选了1个好方法。

我试图创建一个伪超级结构来打印结构数组.我的基本结构如下.

/* 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



1> Jonathan Lef..:

我认为你的设计会失败,但我也不相信我看到的其他答案完全处理了更深层次的原因.

看起来你正在尝试使用C来处理泛型类型,这些东西总是变得毛茸茸.你可以做到,如果你小心,但这并不容易,在这种情况下,我怀疑它是否值得.

更深层次的原因:让我们假设我们已经超越了单纯的句法(或者仅仅是句法)问题.您的代码显示T10CNT包含20,int而T20CNT包含20 long.在现代的64位机器上 - 除了Win64之外 - sizeof(long) != sizeof(int).因此,打印函数中的代码应该区分解除引用int数组和long数组.在C++中,有一个规则,你不应该尝试多态地处理数组,这就是为什么.CMNCNT类型包含3个long值; 尽管阵列的基本类型与T20CNT匹配,但数量上与T10CNT和T20CNT结构不同.

风格建议:我强烈建议避免在名称上引入下划线.通常,以下划线开头的名称保留供实现使用,并用作宏.宏不尊重范围; 如果实现定义了一个宏_cnt,它会破坏你的代码.保留名称有细微差别; 我不打算进入那些细微差别.认为"以下划线开头的名字是保留的"会更简单,它会引导你避免麻烦.

样式建议:您的打印功能无条件地返回成功.那是不明智的; 你的函数应该什么都不返回,这样调用者就不必测试成功或失败(因为它永远不会失败).注意到函数返回状态的仔细编码器将始终测试返回状态,并具有错误处理代码.该代码永远不会执行,因此它已经死了,但任何人(或编译器)都很难确定.

表面修复:暂时,我们可以假设您可以将intlong视为同义词; 但是你必须习惯于认为它们是同义词.该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 *通用寻址机制.

下一个操作添加正确的字节数,以获取isize对象数组的th元素的开头elemsize.

然后第二个演员告诉编译器"相信我 - 我知道我在做什么"并"将此地址视为CMNCNT结构的地址".

从那里,代码很容易.请注意,由于CMNCNT结构包含long值,我过去常常%ld说实话fprintf().

由于您不打算修改此函数中的数据,因此const像我一样使用限定符并不是一个坏主意.

请注意,如果您要忠实于此sizeof(long) != sizeof(int),那么您需要两个单独的代码块(我建议使用单独的函数)来处理'数组int'和'数组long'结构类型.

推荐阅读
手机用户2402851155
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有