在C结构中“解除引用void *'指针”警告的解决方案?(Solution for “dereferencing `void *' pointer” warning in stru

编程入门 行业动态 更新时间:2024-10-11 23:22:09
在C结构中“解除引用void *'指针”警告的解决方案?(Solution for “dereferencing `void *' pointer” warning in struct in C?)

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

/* Type 10 Count */ typedef struct _T10CNT { int _cnt[20]; } T10CNT; ... /* Type 20 Count */ typedef struct _T20CNT { long _cnt[20]; } T20CNT; ...

我创建了下面的结构来打印上述结构的数组。 编译下面的代码片段时,我得到了无效指针错误引用。

typedef struct _CMNCNT { long _cnt[3]; } CMNCNT; static int printCommonStatistics(void *cmncntin, int cmncnt_nelem, int cmncnt_elmsize) { int ii; for(ii=0; ii<cmncnt_nelem; ii++) { CMNCNT *cmncnt = (CMNCNT *)&cmncntin[ii*cmncnt_elmsize]; fprintf(stout,"STATISTICS_INP: %d\n",cmncnt->_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

I was trying to create a pseudo super struct to print array of structs. My basic structures are as follows.

/* Type 10 Count */ typedef struct _T10CNT { int _cnt[20]; } T10CNT; ... /* Type 20 Count */ typedef struct _T20CNT { long _cnt[20]; } T20CNT; ...

I created the below struct to print the array of above mentioned structures. I got dereferencing void pointer error while compiling the below code snippet.

typedef struct _CMNCNT { long _cnt[3]; } CMNCNT; static int printCommonStatistics(void *cmncntin, int cmncnt_nelem, int cmncnt_elmsize) { int ii; for(ii=0; ii<cmncnt_nelem; ii++) { CMNCNT *cmncnt = (CMNCNT *)&cmncntin[ii*cmncnt_elmsize]; fprintf(stout,"STATISTICS_INP: %d\n",cmncnt->_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]); ...

My intention is to have a common function to print all the arrays. Please let me know the correct way of using it.

Appreciate the help in advance.

Edit: The parameter name is changed to cmncntin from cmncnt. Sorry it was typo error.

Thanks, 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 *转换为特定类型。

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 ”来准备代码切成'SO'答案)。

这个投线是做什么的? 我很高兴你问...

第一个操作是将const void *转换为const char * ; 这使您可以对地址执行字节大小的操作。 在标准C之前的日子里, char *被用来代替void *作为通用寻址机制。 下一个操作会添加正确数量的字节以获得大小为elemsize的对象数组的第i个元素的开始。 然后第二个演员告诉编译器“相信我 - 我知道我在做什么”并且“将此地址视为CMNCNT结构的地址”。

从那里,代码很容易。 请注意,由于CMNCNT结构包含long整型值,因此我使用%ld来向fprintf()讲述实情。

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

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

I think your design is going to fail, but I am also unconvinced that the other answers I see fully deal with the deeper reasons why.

It appears that you are trying to use C to deal with generic types, something that always gets to be hairy. You can do it, if you are careful, but it isn't easy, and in this case, I doubt if it would be worthwhile.

Deeper Reason: Let's assume we get past the mere syntactic (or barely more than syntactic) issues. Your code shows that T10CNT contains 20 int and T20CNT contains 20 long. On modern 64-bit machines - other than under Win64 - sizeof(long) != sizeof(int). Therefore, the code inside your printing function should be distinguishing between dereferencing int arrays and long arrays. In C++, there's a rule that you should not try to treat arrays polymorphically, and this sort of thing is why. The CMNCNT type contains 3 long values; different from both the T10CNT and T20CNT structures in number, though the base type of the array matches T20CNT.

Style Recommendation: I strongly recommend avoiding leading underscores on names. In general, names beginning with underscore are reserved for the implementation to use, and to use as macros. Macros have no respect for scope; if the implementation defines a macro _cnt it would wreck your code. There are nuances to what names are reserved; I'm not about to go into those nuances. It is much simpler to think 'names starting with underscore are reserved', and it will steer you clear of trouble.

Style Suggestion: Your print function returns success unconditionally. That is not sensible; your function should return nothing, so that the caller does not have to test for success or failure (since it can never fail). A careful coder who observes that the function returns a status will always test the return status, and have error handling code. That code will never be executed, so it is dead, but it is hard for anyone (or the compiler) to determine that.

Surface Fix: Temporarily, we can assume that you can treat int and long as synonyms; but you must get out of the habit of thinking that they are synonyms, though. The void * argument is the correct way to say "this function takes a pointer of indeterminate type". However, inside the function, you need to convert from a void * to a specific type before you do indexing.

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]); } }

(I like the idea of a file stream called stout too. Suggestion: use cut'n'paste on real source code--it is safer! I'm generally use "sed 's/^/ /' file.c" to prepare code for cut'n'paste into an SO answer.)

What does that cast line do? I'm glad you asked...

The first operation is to convert the const void * into a const char *; this allows you to do byte-size operations on the address. In the days before Standard C, char * was used in place of void * as the universal addressing mechanism. The next operation adds the correct number of bytes to get to the start of the ith element of the array of objects of size elemsize. The second cast then tells the compiler "trust me - I know what I'm doing" and "treat this address as the address of a CMNCNT structure".

From there, the code is easy enough. Note that since the CMNCNT structure contains long value, I used %ld to tell the truth to fprintf().

Since you aren't about to modify the data in this function, it is not a bad idea to use the const qualifier as I did.

Note that if you are going to be faithful to sizeof(long) != sizeof(int), then you need two separate blocks of code (I'd suggest separate functions) to deal with the 'array of int' and 'array of long' structure types.

更多推荐

本文发布于:2023-07-14 19:05:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1106733.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:指针   解决方案   结构   void   Solution

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!