Re: manipulating void* in array



Stijn van Dongen <svd@xxxxxxxxxxxx> wrote:

Your description is very vague, you'd better post some pseudo-code
to illustrate your problem (but please, as little as necessary).
I'll do my best.

> A question about void*. I have a hash library where the hash create
> function accepts functions
> unsigned (*hash)(const void *a)
> int (*cmp) (const void *a, const void *b)
>
> The insert function accepts a void* key argument, and uses the
> functions above to store this argument. It returns something (linked to
> the key) that the caller can store a value in.

You mean the caller first inserts a key, and then fills in the rest
of the data? It doesn't sound like a good interface. Better compute
everything before inserting; insert function needn't return anything.

>The actual key argument
> is always of the same pointer type (as seen in the caller, say foo*).

If you operate on one data type (foo), then there's no advantage in
having void* pointers; use foo* in `hash' and `cmp' (I've noticed
they don't take size argument, therefore they must know the type,
or at least the size, of data they work on), and others. Use void* when
you need generic pointer, when the data you work on is unknown.

>
> Now I would like to have a function, say hash_keys, which returns all
> keys in the hash as a pointer to a malloced array of void*.

As above, you could return an array of `foo*'.

>However,
> there is not really a type I can use.

Why?

>I see two possible solutions.
> The first is to typedef a struct containing a void pointer:
>
> typedef struct {
> void* pp;
> } genpp;
>
> and have hash_keys return genpp* (the size could be written in an int*
> argument
> to hash_keys). This would make accessing the keys cumbersome.

There's no point in returning a struct having only one member. Return
the member.

Some propositions:

/* return array of void* (actually, pointer to its first element)
and it's size in `*size' */
void* hash_keys(size_t *size);

/* return array of void* in `keys' argument, and its size in
the return value; basically same as above, but the meaning
of arguement and return value is reversed */
size_t hash_keys(void* *keys);

/* return array of void*, N+1 elements, the last is null ptr */
void* hash_keys(void);

/* return array and its size as a pair in a struct */
struct { void* a; size_t s; } hash_keys(void);

>
> Solution 2) is illegal C (I think), but it's tempting. hash_keys would
> construct an array of void*-sized elements and copy its key pointers
> there using char* arithmetic.

There's no reason for that, you should just assign one type to another,
an automatic conversion will be performed (no need for casting).

void *pv;
foo *pf;
pv = pf; //okay
pf = pv; //okay

>It would return void* and the caller
> would cast it to foo**.

I don't quite get what you think here, but I think you think wrong.

>For one thing, this assumes sizeof(void*) is
> sizeof(foo*) for all possible foo.

You can never assume that (unless `foo' is `char', which is probably
not what you have).

>For another, I see nothing in the
> standard on void* that would support any of this. However, it feels as
> if approach 2) is conceptually extremely similar to the first and I
> suspect it would work on nearly all platforms/compilers.

I don't see much difference between them. They differ in how
the values are stored in the array.

I don't quite understand what your problem is: is it how to return
an array to the caller, or how to store values in it? You need
to post some code to explain it.

>
> The questions then are,
>
> 1. Did I miss another solution where hash_keys creates some array?
> 2. Is my assessment of 2) correct?

I think solution 2 had unnecessary flaws. You need to explain more
what your real problem is.

> 3. On what kind of platforms/compilers would 2) fail? Outside the scope
> of this newsgroup, I know, but perhaps some kind soul can comment.

If the code is written in a portable manner, then it will fail only
on a broken implementation. If it isn't, It may fail on the same
platform of yours tomorrow, and always on your customers' machines
while you're not watching.

--
Stan Tobias
mailx `echo siXtY@xxxxxxxxxxxxxxxxxxxxxxxxxx | sed s/[[:upper:]]//g`
.



Relevant Pages

  • Re: pass by Reference/value ???
    ... > void foo ... this would be called "passing by reference". ... foo receives a local copy of s and any changes that it makes to s only ... Since s is a pointer, a variable storing the address of s is a pointer to ...
    (comp.lang.cpp)
  • Re: manipulating void* in array
    ... The correct type is void** as Dave pointed out. ... But how does foo* ... I thought your key pointer type was void*. ... > whole array of *copies* of my foo things. ...
    (comp.lang.c)
  • Re: A little help please
    ... Well I guess it would be if I didn't know I was passing an array of ints ... incrementing the pointer by nBytes I was pointing to next array element.? ... array to a void* using a static cast. ...
    (alt.comp.lang.learn.c-cpp)
  • Re: 2-dimensional arrays and functions
    ... Here are my examples again incase you missed it in this pointer pandemonium: ... int main{ ... dynamically created 2D array in ppArray ... void pArrayFunction; ...
    (alt.comp.lang.learn.c-cpp)
  • Re: Can I send char as array argument?
    ... Everything about programming I have learned ... > void main ... to it with a pointer. ... Your solution was to declare a 1-element array of char ...
    (comp.lang.c)