relation between sizeof(void*), sizeof(int) 
Author Message
 relation between sizeof(void*), sizeof(int)

In an earlier discussion I found that

   sizeof(void*) <= sizeof(int)    

does *not* hold in general. How about

  sizeof(int) <= sizeof(void*)

The reason I ask is that I have to write a graph to a file. The
graph's edges are just the pointers from node to node. In addition all
nodes are also stored linearly exactly once in an array, say A, so
that this index can as well represent an edge and is in fact what I
want to write out.

To translate a pointer to the index, I could search it in A, but this
is slow. Instead, before writing I would like to enter indices into
the nodes instead of the pointers somewhat similar to

   for(... i ...) A[i]->edge = (void*)i;

and after writing I would do

   for(... i ...) A[i]->edge = A[A[i]->edge]

Note that I cannot spend the additional memory for this index in a
node. But for portability I am afraid the int..void*..int casting is a
bad idea. Is it more portable to use

typedef struct s_Node {
  ...
  union {
    void *p;
    size_t edge_repesenting_index;
  } edge;
  ...

Quote:
} *Node

  Harald Kirsch

--
----------------+------------------------------------------------------

LION bioscience | +49 6221 4038 172          |        -- Paul Erd?s
--



Mon, 05 Jan 2004 23:02:27 GMT  
 relation between sizeof(void*), sizeof(int)

Quote:

> In an earlier discussion I found that
>    sizeof(void*) <= sizeof(int)
> does *not* hold in general. How about
>   sizeof(int) <= sizeof(void*)

Ditto.

Quote:
> The reason I ask is that I have to write a graph to a file. The
> graph's edges are just the pointers from node to node. In addition all
> nodes are also stored linearly exactly once in an array, say A, so
> that this index can as well represent an edge and is in fact what I
> want to write out.

Good thing, too, as the pointer values are valid only within
the one process and only for the lifetime of the node array.

Quote:
> To translate a pointer to the index, I could search it in A, but this
> is slow. Instead, before writing I would like to enter indices into
> the nodes instead of the pointers somewhat similar to
>    for(... i ...) A[i]->edge = (void*)i;
> and after writing I would do
>    for(... i ...) A[i]->edge = A[A[i]->edge]
> Note that I cannot spend the additional memory for this index in a
> node. But for portability I am afraid the int..void*..int casting is a
> bad idea. Is it more portable to use
> typedef struct s_Node {
>   ...
>   union {
>     void *p;
>     size_t edge_repesenting_index;
>   } edge;
>   ...
> } *Node

Definitely, if you can't afford to use more storage then
use the union.  The code will almost always be just as fast,
as well as portable.  You might want to use a union (typedef)
for all linkage pointers.

However, I don't understand why you need to change pointers
to integers within the node data.  Why not just convert
while writing out:
        fprintf(graph_file, " %lx", (unsigned long)(p - A));
where p is the pointer you want to covert to an index.
--



Tue, 06 Jan 2004 08:41:22 GMT  
 relation between sizeof(void*), sizeof(int)
intptr_t from stdint.h does what you want. It "designates a signed integer
type with the property that any valid pointer to void can be converted to
this type, then converted back to pointer to void, and the result will
compare equal to the original pointer."
--



Tue, 06 Jan 2004 08:41:33 GMT  
 relation between sizeof(void*), sizeof(int)

Quote:

> In an earlier discussion I found that

>    sizeof(void*) <= sizeof(int)    

> does *not* hold in general. How about

>   sizeof(int) <= sizeof(void*)

No. The sizes of pointers and integers have no relation at all.

Richard
--



Tue, 06 Jan 2004 08:39:25 GMT  
 relation between sizeof(void*), sizeof(int)

Quote:

> In an earlier discussion I found that
>    sizeof(void*) <= sizeof(int)    
> does *not* hold in general. How about
>   sizeof(int) <= sizeof(void*)

May be untrue just as easily. Any file format relying on either of the
above reasons has a serious design flaw.

Quote:
> The reason I ask is that I have to write a graph to a file.

Fine. But pointers cannot be (meaningfully) written to a file, anyway,
so what would you need the size of a pointer type, for, in this
context?

Quote:
> Note that I cannot spend the additional memory for this index in a
> node.

Then use a union, like you already guessed, or only do this
temporarily while serialising your data (i.e. preparing for writing
them to file).
--

Even if all the snow were burnt, ashes would remain.
--



Tue, 06 Jan 2004 08:39:41 GMT  
 relation between sizeof(void*), sizeof(int)

Quote:

> intptr_t from stdint.h does what you want. It "designates a signed integer
> type with the property that any valid pointer to void can be converted to
> this type, then converted back to pointer to void, and the result will
> compare equal to the original pointer."

Don't post without context.

intptr_t is not guaranteed to be defined, even in C99, and is not
defined in C89.  Portable code should avoid it.  The union is
portable.

Micah

--
"*I* don't think you understand your question."
                                        -- Tom Plunket
--



Tue, 06 Jan 2004 23:54:07 GMT  
 relation between sizeof(void*), sizeof(int)

[about serializing a graph, the edges of which are just pointers]

Quote:
> >   union {
> >     void *p;
> >     size_t edge_repesenting_index;
> >   } edge;
> >   ...
> > } *Node

> Definitely, if you can't afford to use more storage then
> use the union.  The code will almost always be just as fast,
> as well as portable.  You might want to use a union (typedef)
> for all linkage pointers.

> However, I don't understand why you need to change pointers
> to integers within the node data.  Why not just convert
> while writing out:
>    fprintf(graph_file, " %lx", (unsigned long)(p - A));
> where p is the pointer you want to covert to an index.

Because array A does not contain the nodes themselves but rather
pointers to the nodes. Consequently, an edge leaving from node i would
be A[i]->p. And for exactly one j we have A[i]->p==A[j]. When
serializing node *(A[i]) I need to know j in order to write it out
instead of the pointer.

  Harald Kirsch

--
----------------+------------------------------------------------------

LION bioscience | +49 6221 4038 172          |        -- Paul Erd?s
       *** Please do not send me copies of your posts. ***
--



Tue, 06 Jan 2004 23:54:44 GMT  
 relation between sizeof(void*), sizeof(int)

Quote:

> intptr_t from stdint.h does what you want. It "designates a signed integer
> type with the property that any valid pointer to void can be converted to
> this type, then converted back to pointer to void, and the result will
> compare equal to the original pointer."

Hmm, in fact I rather wanted to use some pointer variable to
temporarily hold an integer value, in fact a size_t (array
index). Looks like I really have to use the union-approach to share
the space portably between the two.

Thanks,
  Harald.

--
----------------+------------------------------------------------------

LION bioscience | +49 6221 4038 172          |        -- Paul Erd?s
       *** Please do not send me copies of your posts. ***
--



Tue, 06 Jan 2004 23:54:52 GMT  
 relation between sizeof(void*), sizeof(int)

Quote:

> intptr_t from stdint.h does what you want. It "designates a signed integer
> type with the property that any valid pointer to void can be converted to
> this type, then converted back to pointer to void, and the result will
> compare equal to the original pointer."

Note that intptr_t does not exist in C89, and may not exist, because it
is optional, in C99.

Richard
--



Tue, 06 Jan 2004 23:54:54 GMT  
 relation between sizeof(void*), sizeof(int)


Quote:
>intptr_t from stdint.h does what you want. It "designates a signed integer
>type with the property that any valid pointer to void can be converted to
>this type, then converted back to pointer to void, and the result will
>compare equal to the original pointer."

in C99? and keep in mind that there is no requirement that there be such
a type.

Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
--



Tue, 06 Jan 2004 23:55:05 GMT  
 relation between sizeof(void*), sizeof(int)

Quote:

> intptr_t from stdint.h does what you want.

No, it doesn't, even if it exists (which is not guaranteed).
He wanted an *index*, not an alternate representation for a pointer.
--



Wed, 07 Jan 2004 14:17:04 GMT  
 relation between sizeof(void*), sizeof(int)

Quote:
>intptr_t from stdint.h does what you want. It "designates a signed integer
>type with the property that any valid pointer to void can be converted to
>this type, then converted back to pointer to void, and the result will
>compare equal to the original pointer."

But, since neither intptr_t nor stdint.h are standard C90 features, you
can't rely on them in portable code that is to be used before the days
when C99 implementations are widely available.

Dan
--
Dan Pop
CERN, IT Division

Mail:  CERN - IT, Bat. 31 1-014, CH-1211 Geneve 23, Switzerland
--



Wed, 07 Jan 2004 23:38:21 GMT  
 relation between sizeof(void*), sizeof(int)

Quote:

> intptr_t is not guaranteed to be defined, even in C99, and is not
> defined in C89.  Portable code should avoid it.  ...

Not defined by C89 is no reason to avoid it, because it is easy
enough to provide your own <stdint.h> if one isn't already provided
by the compiler vendor.  The main problem is that there might not be
a suitable type in an implementation.  Portable code *could* use it,
but only conditionally upon a test for a corresponding macro; since
the program would need to provide an alternative algorithm when the
type and macro are not defined, why not just use the alternative in
the first place.
--



Thu, 08 Jan 2004 00:14:41 GMT  
 relation between sizeof(void*), sizeof(int)

Quote:



>>>   union {
>>>     void *p;
>>>     size_t edge_repesenting_index;
>>>   } edge;

If you mean
  node->edge.p = something;
  printf("%lx, (unsigned long) node->edge.edge_repesenting_index);
that fails if size_t has padding bits which are used in the void*.

Use the %p format instead, unless you need to stay compatible with K&R
printf.  (And remember to read/write void pointers, which may have
different representation than your node pointers.)

Another variant: fwrite(&ptr, sizeof(ptr), 1, file) to a binary file.
The file will be unportable, but so will integers and %p output.

Quote:
>> However, I don't understand why you need to change pointers
>> to integers within the node data.  Why not just convert
>> while writing out:
>>        fprintf(graph_file, " %lx", (unsigned long)(p - A));
>> where p is the pointer you want to covert to an index.

> Because array A does not contain the nodes themselves but rather
> pointers to the nodes.  Consequently, an edge leaving from node i
> would be A[i]->p.

That would make sense, if you didn't add:

Quote:
> And for exactly one j we have A[i]->p==A[j].

Now I don't get it.  I take it you are going to write A[i]->p, but that
still is *some* member of the A array, right?  So you can subtract A
from it and get an integer, and add A back to get the pointer you
wrote.

Quote:
> When serializing node *(A[i]) I need to know j in order to write it
> out instead of the pointer.

A[j] == A + j, so if A[i]->p == A[j], then j == A[i]->p - A.

If that was a typo and what you need is to find i given j,
you could build a temporary hash table which maps j to i.

--
Hallvard
--



Sun, 11 Jan 2004 06:52:59 GMT  
 relation between sizeof(void*), sizeof(int)

Quote:



> >>>   union {
> >>>     void *p;
> >>>     size_t edge_repesenting_index;
> >>>   } edge;

> If you mean
>   node->edge.p = something;
>   printf("%lx, (unsigned long) node->edge.edge_repesenting_index);
> that fails if size_t has padding bits which are used in the void*.

This was not about writing pointers to a file, which is useless most
of the time. The edge_repesenting_index is an index into a pointer
array which holds every possible edge.p exactly once such that

   void *keep = edge.p;
   edge.edge_repesenting_index = something;
   A[edge.edge_repesenting_index] == keep;

The point is to set the edge_repesenting_index only temporarily during
writeout of the data structure. During that time, the real pointers
are kept somewhere else.

[snip]

Quote:
> > Because array A does not contain the nodes themselves but rather
> > pointers to the nodes.  Consequently, an edge leaving from node i
> > would be A[i]->p.

> That would make sense, if you didn't add:

> > And for exactly one j we have A[i]->p==A[j].

> Now I don't get it.  I take it you are going to write A[i]->p, but that
> still is *some* member of the A array, right?  So you can subtract A
> from it and get an integer, and add A back to get the pointer you
> wrote.

> > When serializing node *(A[i]) I need to know j in order to write it
> > out instead of the pointer.

> A[j] == A + j, so if A[i]->p == A[j], then j == A[i]->p - A.

Hmm, I thought that in contrast rather

  &(A[j])==A+j and A[j]==*(A+j)

holds for rvalues in general.

  Harald.
--
----------------+------------------------------------------------------

LION bioscience | +49 6221 4038 172          |        -- Paul Erd?s
       *** Please do not send me copies of your posts. ***
--



Sun, 11 Jan 2004 22:32:15 GMT  
 
 [ 16 post ]  Go to page: [1] [2]

 Relevant Pages 

1. sizeof(void*) versus sizeof(foo*)

2. sizeof(int) sizeof(long) etc.

3. sizeof (struct) ! = sizeof struct elements

4. sizeof without sizeof

5. sizeof a/sizeof *a

6. sizeof(foo) -1 or sizeof(foo)

7. Problem with sizeof of a struct void pointer

8. void *, ptr arithmetic and sizeof()

9. sizeof void*

10. sizeof(void) ??

11. I wish ANSI-C sizeof (void) == 1 (was Re: preprocessing subterfuge)

12. Question about sizeof (*(void *))

 

 
Powered by phpBB® Forum Software