引用void指针 [英] Deferencing void pointer

查看:72
本文介绍了引用void指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不敢相信我一直在努力解决这个问题几个小时,而且我不能相信我找不到有人要求类似的解决方案在

新闻组中。难怪我非常讨厌C,而且每当我拿到

教科书时,最终会把它们扔到墙上愤怒。多数民众赞成

现在已经持续了10年。


无论如何,我有:


typedef struct _record {

int age;

}记录;


typedef struct _LinkedList {

void * data;

struct _LinkedList * next;

} LinkedList;


我可以将项目添加到我的链表,遍历列表等。但是我

无法获取列表中的数据。


curr_ptr = head;

while(curr_ptr!= NULL) {

printf(" traverse:this =%p data =%d \ n",

curr_ptr,curr_ptr-> data-> age); < br $>
}


导致错误:

警告:引用''void *''指针

请求会员''年龄''不是结构或联盟。


我知道我必须投它或什么......但我不能想象一下

out!

Arrgh!


Doug

I can''t believe I''ve been trying to work this out for hours now, and I
can''t believe I couldn''t find someone asking for a similar solution in
the newsgroups. No wonder I hate C so much, and every time I get the
textbooks out end up throwing them against the wall in rage. Thats
been going on for 10 years now.

Anyway, I have:

typedef struct _record {
int age;
} record;

typedef struct _LinkedList {
void *data;
struct _LinkedList *next;
} LinkedList;

I can add items to my linked list, traverse the list etc. However I
CANNOT get the data OUT of the list.

curr_ptr = head;
while ( curr_ptr != NULL ) {
printf ("traverse: this=%p data=%d\n",
curr_ptr, curr_ptr->data->age);
}

This results in the error:
warning: deferencing ''void *'' pointer
request for member ''age'' in something not a structure or union.

I know I have to cast it or something.... but I just can''t figure it
out!
Arrgh!

Doug

推荐答案

Douglas Garstang写道:
Douglas Garstang wrote:
我不敢相信我一直在努力工作几个小时,而且我已经>不能相信我找不到有人在新闻组中要求类似的解决方案。难怪我非常讨厌C,而且每次我拿到
教科书都会最终把它们扔到墙上愤怒。多数民众赞成已经持续了10年。


< shrug>你听起来好像需要更好的教科书。

无论如何,我有:

typedef struct _record {
int age;
} record;

typedef struct _LinkedList {
void * data;
struct _LinkedList * next;
} LinkedList;


(一个侧点:我过去常常这样做,但后来我发现

以前导下划线开头的名称是为实现保留的。所以我

开始把下划线放在end_,而__ works_ just_

as_ well_和_ has_ the_ virtue_ of_ correctness_。)

我可以将项目添加到我的链接列表,遍历列表等。但是我无法获取列表中的数据。

curr_ptr = head;
while(curr_ptr!= NULL) {
printf(" traverse:this =%p data =%d \ n",
curr_ptr,curr_ptr-> data-> age);
}

这会导致错误:
警告:引用''void *''指针
请求成员''age''不是结构或联合。


不,你不需要施放(除了打印实际的指针值)。我想b / b
假设在这种情况下你的数据指针指向一个类型为

record的结构。如果是的话,那么...


curr_ptr = head;

{

while(curr_ptr!= NULL)

{

record * p = curr_ptr-> data;

printf(" traverse:this =%p data =%d \ n" ,

(void *)curr_ptr,p-> age);


curr_ptr = curr_ptr-> next;

}

}

Arrgh!
I can''t believe I''ve been trying to work this out for hours now, and I
can''t believe I couldn''t find someone asking for a similar solution in
the newsgroups. No wonder I hate C so much, and every time I get the
textbooks out end up throwing them against the wall in rage. Thats
been going on for 10 years now.
<shrug> You sound like you need better textbooks.

Anyway, I have:

typedef struct _record {
int age;
} record;

typedef struct _LinkedList {
void *data;
struct _LinkedList *next;
} LinkedList;
(A side-point: I used to do this too, but then I discovered that names that
begin with leading underscores are reserved for the implementation. So I
started putting the underscores on the end_ instead_, which_ works_ just_
as_ well_ and_ has_ the_ virtue_ of_ correctness_.)

I can add items to my linked list, traverse the list etc. However I
CANNOT get the data OUT of the list.

curr_ptr = head;
while ( curr_ptr != NULL ) {
printf ("traverse: this=%p data=%d\n",
curr_ptr, curr_ptr->data->age);
}

This results in the error:
warning: deferencing ''void *'' pointer
request for member ''age'' in something not a structure or union.

I know I have to cast it or something.... but I just can''t figure it
out!
No, you don''t need to cast (except to print the actual pointer value). I
presume that in this case your data pointer points to a structure of type
record. If so, then...

curr_ptr = head;
{
while(curr_ptr != NULL)
{
record *p = curr_ptr->data;
printf ("traverse: this=%p data=%d\n",
(void *)curr_ptr, p->age);

curr_ptr = curr_ptr->next;
}
}
Arrgh!




现在感觉好些了吗? :-)


-

Richard Heathfield: biwel@eton.powernet.co.uk

Usenet是一个奇怪的地方。 - Dennis M Ritchie,1999年7月29日。

C FAQ: http://www.eskimo.com/~scs/C-faq/top.html

K& R答案,C书等:< a rel =nofollowhref =http://users.powernet.co.uk/etontarget =_ blank> http://users.powernet.co.uk/eton



Feeling better now? :-)

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton


2003年11月15日星期六21:44:00 -0800,Douglas Garstang写道:
On Sat, 15 Nov 2003 21:44:00 -0800, Douglas Garstang wrote:
typedef struct _record {
int年龄;
}记录;

typedef struct _LinkedList {
void * data;
struct _LinkedList * next;
} LinkedList;

我可以将项目添加到我的链表,遍历列表等。但是我无法获取列表中的数据。

curr_ptr = head;
while( curr_ptr!= NULL){
printf(" traverse:this =%p data =%d \ n",
curr_ptr,curr_ptr-> data-> age);
}

这会导致错误:
警告:引用''void *''指针
请求成员''age''不是结构或联合。
typedef struct _record {
int age;
} record;

typedef struct _LinkedList {
void *data;
struct _LinkedList *next;
} LinkedList;

I can add items to my linked list, traverse the list etc. However I
CANNOT get the data OUT of the list.

curr_ptr = head;
while ( curr_ptr != NULL ) {
printf ("traverse: this=%p data=%d\n",
curr_ptr, curr_ptr->data->age);
}

This results in the error:
warning: deferencing ''void *'' pointer
request for member ''age'' in something not a structure or union.




Richard给出了你是一个很好的答案,所以我不会为你写任何代码。

然而,我想我可能会试着找到问题的根源。


在我看来,你(至少在这种情况下)混淆了你对数据结构的了解以及编译器对数据结构的了解

数据结构。


查看你的struct LinkedList声明:你已声明数据

作为指向void的指针。这告诉编译器每个成员每个成员LinkedList的每个成员都是一个通用指针。它可以指向任何东西。
可以指向任何东西。 *你*知道你的代码使用

数据来指向struct记录对象,但编译器并不知道
。它只知道数据可能指向什么




因此,当您尝试通过解除引用来检索记录时

curr_ptr->数据,编译器别无选择,只能抱怨。它确实没有知道,在这种情况下,curr_ptr->数据是指向结构记录的
。所以它说(释义):


你要我从

中检索成员''年龄'的价值curr_ptr的结构 - >数据指向,但我不能这样做,

因为据我所知,curr_ptr->数据没有指向结构
$完全是b $ b!


因此,为了访问您知道的结构记录的成员

curr_ptr->数据指向,你必须将这些信息提供给编译器的
。在这种情况下,您必须指定curr_ptr-> data

指向结构记录。理查德告诉你最干净的方式

这样做,使用临时变量:


记录* p = curr_ptr->数据;

printf(" data:data =%d \ n",p-> age);


我建议你在这种情况下使用临时变量作为

理查德建议。我将向您展示如何投射

curr_ptr->数据,这样您就可以看到它实际上只是告诉编译器什么是
有点像curr_ptr->数据指向

到:


printf(" data:data =%d \ n",((记录) *)curr_ptr-> data) - > age);


在这种情况下,强制转换通知编译器curr_ptr-data是

指向一个记录。然后编译器能够将

curr_ptr->数据转换为指向记录的指针,然后访问指向记录的年龄

成员。


-Sheldon



Richard gave you a good answer, so I won''t write any code for you.
However, I thought I might try to get to the root of your problem.

It seems to me that you are (at least in this case) confusing what
you know about the data structure and what the compiler knows about
the data structure.

Look at your struct LinkedList declaration: You have declared data
as a pointer to void. This tells the compiler that every member
called data of every struct LinkedList is a generic pointer. It
can point to anything at all. *You* know that your code is using
data to point at struct record objects, but the compiler doesn''t
know that. All it knows is that data could be pointing at anything
at all.

Therefore, when you try to retrieve a record by dereferencing
curr_ptr->data, the compiler has no choice but to complain. It does
not have the knowledge that, in this situation, curr_ptr->data is
pointing at a struct record. So it says (paraphrased):

"You are asking me to retrieve the value of the member ''age'' from
the struct that curr_ptr->data is pointing to, but I can''t do that,
because as far as I know, curr_ptr->data isn''t pointing to a struct
at all!"

So, in order to access members of the struct record that you know
curr_ptr->data is pointing to, you have to give that information to
the compiler. You have to specify that, in this case, curr_ptr->data
is pointing to a struct record. Richard showed you the cleanest way
to do that, use a temporary variable:

record *p = curr_ptr->data;
printf("data: data=%d\n", p->age);

I recommend you use temporary variables in situations like this as
Richard suggested. I will show you how it would be possible to cast
curr_ptr->data so you can see that it''s really just a matter of
telling the compiler what kind of thing curr_ptr->data is pointing
to:

printf("data: data=%d\n", ((record *)curr_ptr->data)->age);

In this case, the cast informs the compiler that curr_ptr-data is
pointing to a record. The compiler is then able to convert
curr_ptr->data into a pointer to record, and then access the age
member of the record being pointed to.

-Sheldon


Richard Heathfield< do ****** @ address.co.uk.invalid>在消息新闻中写道:< bp ********** @ hercules.btinternet.com> ...
Richard Heathfield <do******@address.co.uk.invalid> wrote in message news:<bp**********@hercules.btinternet.com>...
Douglas Garstang写道:
Douglas Garstang wrote:
我不敢相信我一直在努力工作几个小时,而且我无法相信我找不到有人要求类似的解决方案
新闻组。难怪我非常讨厌C,而且每次我拿到
教科书都会最终把它们扔到墙上愤怒。多数民众赞成已经持续了10年。
I can''t believe I''ve been trying to work this out for hours now, and I
can''t believe I couldn''t find someone asking for a similar solution in
the newsgroups. No wonder I hate C so much, and every time I get the
textbooks out end up throwing them against the wall in rage. Thats
been going on for 10 years now.



< shrug>你听起来好像需要更好的教科书。



<shrug> You sound like you need better textbooks.


无论如何,我有:

typedef struct _record {
int age;
} record;

typedef struct _LinkedList {
void * data;
struct _LinkedList * next;
} LinkedList;

Anyway, I have:

typedef struct _record {
int age;
} record;

typedef struct _LinkedList {
void *data;
struct _LinkedList *next;
} LinkedList;



(一个侧点:我过去常常这样做,但后来我发现以前导下划线开头的名称是为实现保留的。所以我开始把下划线放在最后_ instead_,which_ works_ just_
as_ well_和_ has_ the_ virtue_ of_ correctness_。)



(A side-point: I used to do this too, but then I discovered that names that
begin with leading underscores are reserved for the implementation. So I
started putting the underscores on the end_ instead_, which_ works_ just_
as_ well_ and_ has_ the_ virtue_ of_ correctness_.)


我可以将项目添加到我的链表,遍历列表等。但是我无法获取列表中的数据。

curr_ptr = head;
while(curr_ptr!= NULL){
printf(" traverse:this = %p data =%d \ n",
curr_ptr,curr_ptr-> data-> age);
}
这导致错误:
w arning:引用''void *''指针
请求成员''年龄''不是结构或联合。

我知道我必须投它或什么......但是我无法想象它出来了!

I can add items to my linked list, traverse the list etc. However I
CANNOT get the data OUT of the list.

curr_ptr = head;
while ( curr_ptr != NULL ) {
printf ("traverse: this=%p data=%d\n",
curr_ptr, curr_ptr->data->age);
}

This results in the error:
warning: deferencing ''void *'' pointer
request for member ''age'' in something not a structure or union.

I know I have to cast it or something.... but I just can''t figure it
out!



不,你不需要施放(除了打印实际的指针值)。我认为在这种情况下你的数据指针指向一个类型为
记录的结构。如果是的话,那么...

curr_ptr = head;
{while /(curr_ptr!= NULL)
{
记录* p = curr_ptr- >数据;
printf(" traverse:this =%p data =%d \ n",
(void *)curr_ptr,p-> age);

curr_ptr = curr_ptr-> next;
}
}



No, you don''t need to cast (except to print the actual pointer value). I
presume that in this case your data pointer points to a structure of type
record. If so, then...

curr_ptr = head;
{
while(curr_ptr != NULL)
{
record *p = curr_ptr->data;
printf ("traverse: this=%p data=%d\n",
(void *)curr_ptr, p->age);

curr_ptr = curr_ptr->next;
}
}

Arrgh!



现在感觉好点了? : - )



Feeling better now? :-)




谢谢理查德,我感觉好多了5分钟。现在我已经b
$ b到达了我的下一个绊脚石。我正在努力使列表功能

泛型。我的追加函数确实有这样的东西:


int list_append(LinkedList ** list,void * data){


LinkedList * new_item;


if((new_item ==(LinkedList *)malloc(sizeof(LinkedList)))==

NULL){

返回-1;

}

new_item-> data = data

....


(顺便说一下,我不知道为什么指针指针(即**列表)让我

返回函数参数中的列表指针而不必

使用退货声明......我只知道它有效,因为我已经看过

其他人这样做了!Arrrgh!)


但是,我发现因为我只是在每个节点中保留一个指向数据的指针,每次我添加一个具有不同值的新节点时,

所有节点得到更新。


所以,我将我的代码更改为:

int list_append(LinkedList ** list,void * data,int data_size){


LinkedList * new_i tem;

void * data_blk;


if((new_item ==(LinkedList *)malloc(sizeof(LinkedList)))==

NULL){

返回-1;

}

if((data_blk ==(void *)malloc(data_size) )== NULL){

返回-1;

}

memcpy(data_blk,data,sizeof(data))

new_item-> data = data_blk;

....


再次,使用memcpy不是我只是KNEW会工作。

我记得几年前我用它时花了几个小时

来研究它。在C中没有任何东西对我来说很自然......)


这似乎不是一个完美的解决方案。该函数无法知道数据的大小,因为它处理空洞。唯一的方法

我能看到让它工作的是将数据的大小传递给

函数。还有更好的办法吗?


顺便说一句,我有一大堆教科书。他们不可能都坏。


道格。



Thanks Richard, well I felt better for literally 5 minutes. Now I''ve
reached my next stumbling block. I''m trying to make the list functions
generic. I did have something like this in my append function:

int list_append ( LinkedList **list, void *data ) {

LinkedList *new_item;

if ( (new_item == (LinkedList *)malloc(sizeof(LinkedList))) ==
NULL ) {
return -1;
}
new_item->data = data
....

(btw, I don''t know why the pointer to a pointer (ie **list) lets me
return the list pointer in the function arguments without having to
use a return statement... I just know it works because I''ve seen
others do it! Arrrgh!)

However, I found that because I was only keeping a pointer to the data
in each node, every time I added a new node with a different value,
all the nodes got updated.

So, I changed my code to:
int list_append ( LinkedList **list, void *data, int data_size ) {

LinkedList *new_item;
void *data_blk;

if ( (new_item == (LinkedList *)malloc(sizeof(LinkedList))) ==
NULL ) {
return -1;
}
if ( (data_blk == (void *)malloc(data_size)) == NULL ) {
return -1;
}
memcpy ( data_blk, data, sizeof(data))
new_item->data = data_blk;
....

Once again, the use of memcpy is not something I just KNEW would work.
I remembered I''d used it a few years ago when I spent hours
researching it. NOTHING in C comes naturally to me...)

This doesn''t seem like a perfect solution. The function has no way to
know the size of the data because its working with voids. The only way
I can see to make it work is to pass the size of the data to the
function. Is there a better way?

Btw, I have a HUGE pile of textbooks. They can''t all be bad.

Doug.


这篇关于引用void指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆