relation between sizeof(void*), sizeof(int)
Author |
Message |
Harald Kirsc #1 / 16
|
 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 |
|
 |
Douglas A. Gwy #2 / 16
|
 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 |
|
 |
Stephen Bensle #3 / 16
|
 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 |
|
 |
Richard B #4 / 16
|
 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 |
|
 |
Hans-Bernhard Broeke #5 / 16
|
 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 |
|
 |
Micah Cowa #6 / 16
|
 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 |
|
 |
Harald Kirsc #7 / 16
|
 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 |
|
 |
Harald Kirsc #8 / 16
|
 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 |
|
 |
Richard B #9 / 16
|
 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 |
|
 |
Francis Glassboro #10 / 16
|
 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 |
|
 |
Douglas A. Gwy #11 / 16
|
 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 |
|
 |
Dan P #12 / 16
|
 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 |
|
 |
Douglas A. Gwy #13 / 16
|
 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 |
|
 |
Hallvard B Furuset #14 / 16
|
 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 |
|
 |
Harald Kirsc #15 / 16
|
 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 |
|
|
Page 1 of 2
|
[ 16 post ] |
|
Go to page:
[1]
[2] |
|