LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 03-04-2010, 11:14 AM   #1
thandermax
Member
 
Registered: Jun 2005
Distribution: OpenSUSE 10.3 , 11.2 , Solaris 10, Ubuntu 9.10
Posts: 84

Rep: Reputation: 16
Question Correct behavior of void* pointers - Clarification needed


I'm used to program in old 16bit C and 32bit x86 era . In old days we could use void* type pointers to point to any arbitrary structure/string/class and we could easily de-reference any void* pointers to get any kind of data.

So previously we could use this type of code :

Code:
typedef struct {
  int val;
  long long lval;
  void* next;  
}mystr;

mystr first,second;
 ...
 ...

void* ptr = &first;
   while(ptr)
   {
    printf("val = %d , lval = %lx\n",((mystr)(*ptr)).val,((mystr)(*ptr)).lval);
     
     ptr =((mystr)(*ptr)).next;
   }
I recently updated my distribution to x86-64, I don't know whether it is due to GCC 4 compiler or for 64bit compiler I can't use previous code. It throws this error :
Quote:
voidtest1.c:26: warning: dereferencing ‘void *’ pointer
voidtest1.c:26: error: void value not ignored as it ought to be
I tried many variation of casting , but no positive result.

Only way I could fix it by changing my code like this :
Code:
typedef struct {
  int val;
  long long lval;
  void* next;  
}mystr;

mystr first,second;
 ...
 ...

void* ptr = &first;
   while(ptr)
   {
     mystr* tptr = (mystr*) ptr;
    printf("val = %d , lval = %lx\n",(*tptr).val,(*tptr).lval);
     
     ptr =(*tptr).next;
   }




I'm asking this question as it is common in many current linux (x86-64) distribution (I have tested with Ubuntu 9.10 , OpenSuse 11.2 ]


This is more problematic with GTK library. In GTK , we are used to pass many arbitrary user supplied data via gpointer . For example in signals , menubar and other places.

If anybody checks the declaration it is defined as below

Code:
#define gpointer void*
Now due to this change , we can't use gpointer properly in x86-64 linux and GCC 4.x .

Many old gtk programs fails to compile due to this type of void* problem




Any ideas about how to properly use void* in x86-64 version ?
and what we should avoid while using void* ?



I am suggesting others to verify/experiment void* related problem on your own and let me know the result.


Thanks in advance.

Last edited by thandermax; 03-04-2010 at 11:16 AM.
 
Old 03-04-2010, 11:49 AM   #2
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
If you mean to have a structure with one field of it pointing to a structure of the same type, you do not need to use 'void *' pointer.

See, for example,

http://members.rediff.com/vishalini/cfaq.htm (I can't seem to define a linked list successfully) and/
or
http://publications.gbdirect.co.uk/c...tructures.html (6.2.2. Linked lists and other structures).
 
Old 03-04-2010, 12:08 PM   #3
thandermax
Member
 
Registered: Jun 2005
Distribution: OpenSUSE 10.3 , 11.2 , Solaris 10, Ubuntu 9.10
Posts: 84

Original Poster
Rep: Reputation: 16
Smile Thanks ... but

Quote:
Originally Posted by Sergei Steshenko View Post
If you mean to have a structure with one field of it pointing to a structure of the same type, you do not need to use 'void *' pointer.

See, for example,

http://members.rediff.com/vishalini/cfaq.htm (I can't seem to define a linked list successfully) and/
or
http://publications.gbdirect.co.uk/c...tructures.html (6.2.2. Linked lists and other structures).

Thanks for your reply .

Yes I could do it.

But my question is about why I can't use void* in x86-64 bit (gcc 4.4 compiler) ?

Even this code does not work :

Code:
void *ptr = &first;

  ((mystr)(*ptr)).val = 1;    //fails here to dereference *ptr


Let me give you a GTK example :

Code:
typedef void* gpointer;


#define             gtk_signal_connect(GtkObject object,char * name,GCallback func,gpointer func_data)

//The above function is used to attach event handler to any Gtk object such as button,menu etc. 
// func_data is used to pass user supplied arbitrary data , typical usage like below

static void button_clicked_int (GtkButton* button, gpointer func_data)
{
	g_print ("button pressed: %d\n", (GtkObject) (func_data).myvalue);
}


Now as gpointer is void* , the above program fails to compile with :
Code:
voidtest1.c:24: warning: dereferencing ‘void *’ pointer
voidtest1.c:24: error: invalid use of void expression
or with other way of casting :

Code:
voidtest1.c:25: warning: dereferencing ‘void *’ pointer              
voidtest1.c:25: error: void value not ignored as it ought to be
 
Old 03-04-2010, 12:18 PM   #4
smeezekitty
Senior Member
 
Registered: Sep 2009
Location: Washington U.S.
Distribution: M$ Windows / Debian / Ubuntu / DSL / many others
Posts: 2,339

Rep: Reputation: 231Reputation: 231Reputation: 231
Because we are far enough into the '64 bit' world to start using it day-to-day.
 
Old 03-04-2010, 12:22 PM   #5
thandermax
Member
 
Registered: Jun 2005
Distribution: OpenSUSE 10.3 , 11.2 , Solaris 10, Ubuntu 9.10
Posts: 84

Original Poster
Rep: Reputation: 16
Cool

Quote:
Originally Posted by smeezekitty View Post
Because we are far enough into the '64 bit' world to start using it day-to-day.

Yup , and this type of strange things just pushes the adaptation down.

With new architecture comes new challenges

But it'll be helpful to know the reason anyway.
 
Old 03-04-2010, 12:23 PM   #6
Xyro
LQ Newbie
 
Registered: Aug 2009
Location: Canada
Distribution: Ubuntu 9.04
Posts: 22

Rep: Reputation: 19
You cannot dereference a void pointer.

You have:

Code:
((mystr)(*ptr)).val = 1;
The problem is this "*ptr". You need to cast it to something before you dereference it.

You want:

Code:
(*(mystr*)ptr)).val = 1;
or better yet:

Code:
((mystr*)ptr)->val = 1;
*** EDITED LAST CODE TO CORRECT

I didn't try this, might have made a dumb mistake. Try and let me know if it worked.

PS: It has nothing to do with the architecture.

Last edited by Xyro; 03-04-2010 at 12:45 PM. Reason: PS + Correction
 
1 members found this post helpful.
Old 03-04-2010, 12:29 PM   #7
thandermax
Member
 
Registered: Jun 2005
Distribution: OpenSUSE 10.3 , 11.2 , Solaris 10, Ubuntu 9.10
Posts: 84

Original Poster
Rep: Reputation: 16
Thumbs up Atlast ...

Quote:
Originally Posted by Xyro View Post

Code:
(*(mystr*)ptr).val = 1;
Above code works ....

Last one still fails.


So I presume I first need to cast the ptr to proper type and then dereference .
 
Old 03-04-2010, 12:39 PM   #8
Xyro
LQ Newbie
 
Registered: Aug 2009
Location: Canada
Distribution: Ubuntu 9.04
Posts: 22

Rep: Reputation: 19
Quote:
Originally Posted by thandermax View Post
Above code works ....

Last one still fails.


So I presume I first need to cast the ptr to proper type and then dereference .
Yep.

Code:
((mystr*)ptr)->val = 1;
should do the trick then

Last edited by Xyro; 03-04-2010 at 12:45 PM.
 
Old 03-04-2010, 02:33 PM   #9
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by thandermax View Post
I'm used to program in old 16bit C and 32bit x86 era . In old days we could use void* type pointers to point to any arbitrary structure/string/class and we could easily de-reference any void* pointers to get any kind of data.
I don't believe correct C ever allowed that. I don't think any of the difference you describe is x86_64 vs older architectures (as you seem to assume). Maybe the difference is current GCC vs. older incorrect compilers. Maybe the difference is between what you're doing now and what you think you remember.

Code:
void* ptr = &first;
...
((mystr)(*ptr)).lval
That is just wrong. Not incompatible with x86_64, not (just) incompatible with current gcc, just wrong!

As others pointed out, correct code is
(*((mystr*)ptr)).lval
while more readable code is
((mystr*)ptr)->lval

Quote:
I recently updated my distribution to x86-64, I don't know whether it is due to GCC 4 compiler or for 64bit compiler
Hopefully neither. The old code was just wrong.

Quote:
If anybody checks the declaration it is defined as below

Code:
#define gpointer void*
YUCK!!!

WHY!?!

What might you expect the meaning to be if you wrote
Code:
gpointer p1, p2;
Why would you abuse #define to do badly what can be done well with typedef?

Quote:
and what we should avoid while using void* ?
The usual x86_64 specific problem is casting between pointers and int's. That is common (bad) practice in 32 bit x86 and breaks in x86_64.

Casting between void* and other pointer types is no trickier in x86_64 than in generic architectures.
 
  


Reply

Tags
bit, pointer, void



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
void pointers charlitos Programming 17 03-31-2009 05:24 AM
LXer: Generic Function Pointers In C And Void * LXer Syndicated Linux News 0 02-22-2009 07:10 PM
what are void pointers used for? aditya1 Linux - General 10 03-14-2005 03:06 PM
void pointers suchi_s Programming 9 11-08-2004 03:05 PM
Clarification needed..... SomeEverydayNob Linux - Newbie 3 05-10-2003 02:07 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 02:57 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration