Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > int** to void**

Reply
Thread Tools

int** to void**

 
 
John
Guest
Posts: n/a
 
      01-06-2010
Hi All,

I wrote a function in C and compiled in gcc, I got a warning such as:

.../test/test.c:26: warning: passing arg 1 of `ORCdarrayfree' from
incompatib
le pointer type

Then I goto 26th line, I found the function ORCdarrayfree have a
parameter with type void**,
but I passed int** to it.

So anyone can explain it for me and help me avoid this warning?

Thanks!
 
Reply With Quote
 
 
 
 
Ralph Malph
Guest
Posts: n/a
 
      01-06-2010
int** i;
void** v=(void**) i;

John wrote:
> Hi All,
>
> I wrote a function in C and compiled in gcc, I got a warning such as:
>
> ../test/test.c:26: warning: passing arg 1 of `ORCdarrayfree' from
> incompatib
> le pointer type
>
> Then I goto 26th line, I found the function ORCdarrayfree have a
> parameter with type void**,
> but I passed int** to it.
>
> So anyone can explain it for me and help me avoid this warning?
>
> Thanks!

 
Reply With Quote
 
 
 
 
Seebs
Guest
Posts: n/a
 
      01-06-2010
On 2010-01-06, John <(E-Mail Removed)> wrote:
> So anyone can explain it for me and help me avoid this warning?


Quite simply, you can't do that.

You can convert void* to int*, but not void** to int**.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / http://www.velocityreviews.com/forums/(E-Mail Removed)
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      01-06-2010
Ralph Malph <(E-Mail Removed)> writes:
> John wrote:
>> I wrote a function in C and compiled in gcc, I got a warning such as:
>>
>> ../test/test.c:26: warning: passing arg 1 of `ORCdarrayfree' from
>> incompatib
>> le pointer type
>>
>> Then I goto 26th line, I found the function ORCdarrayfree have a
>> parameter with type void**,
>> but I passed int** to it.
>>
>> So anyone can explain it for me and help me avoid this warning?

>
> int** i;
> void** v=(void**) i;


[top-posting corrected]

Using a cast to silence a warning is almost never the right thing
to do.

void* is a generic pointer type, in the sense that you can convert
from any pointer type (excluding pointer-to-function types) to void*
and back again without loss of information.

There is no generic pointer-to-pointer type.

I don't know what ORCdarrayfree, but apparently it requires an
argument of type void**, most likely pointing to the first element
of an array of void*. The int** argument you're passing is probably
a pointer to the first element of an array of int*. void* and int*
are distinct and incompatible types.

You need to pass a valid void** value to ORCdarrayfree. The question
is how you can obtain such a value. We can't guess at an answer
without knowing more about ORCdarrayfree and what you're trying to
pass to it.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      01-06-2010
Seebs <(E-Mail Removed)> writes:
> On 2010-01-06, John <(E-Mail Removed)> wrote:
>> So anyone can explain it for me and help me avoid this warning?

>
> Quite simply, you can't do that.
>
> You can convert void* to int*, but not void** to int**.


Correction: You *can* convert from void** to int** (or, in this case,
from int** to void**) by using a cast, but you almost certainly
shouldn't.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Donkey Hottie
Guest
Posts: n/a
 
      01-06-2010
On 6.1.2010 6:03, Keith Thompson wrote:
> Seebs<(E-Mail Removed)> writes:
>> On 2010-01-06, John<(E-Mail Removed)> wrote:
>>> So anyone can explain it for me and help me avoid this warning?

>>
>> Quite simply, you can't do that.
>>
>> You can convert void* to int*, but not void** to int**.

>
> Correction: You *can* convert from void** to int** (or, in this case,
> from int** to void**) by using a cast, but you almost certainly
> shouldn't.
>


Why not? If pointer arithmetic is not wanted, what do we miss? A pointer
is pointer no matter what.

--
http://www.iki.fi/jarif/

You will inherit millions of dollars.
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      01-06-2010
Donkey Hottie <(E-Mail Removed)> writes:
> On 6.1.2010 6:03, Keith Thompson wrote:
>> Seebs<(E-Mail Removed)> writes:
>>> On 2010-01-06, John<(E-Mail Removed)> wrote:
>>>> So anyone can explain it for me and help me avoid this warning?
>>>
>>> Quite simply, you can't do that.
>>>
>>> You can convert void* to int*, but not void** to int**.

>>
>> Correction: You *can* convert from void** to int** (or, in this case,
>> from int** to void**) by using a cast, but you almost certainly
>> shouldn't.

>
> Why not? If pointer arithmetic is not wanted, what do we miss? A
> pointer is pointer no matter what.


void* and int* are incompatible types.

Consider an implementation where void* is 64 bits and int* is 32
bits (such an implementation is certainly permitted, and there could
be valid reasons for it). Then the function expects a void** that
points to the first element of an array of void* objects, each of
which is 64 bits -- but you're passing it an int** that points to the
first element of an array of int* objects, each of which is 32 bits.

Conversions from one pointer type to another can be safe in certain
cases. Interpreting a stored object of one pointer type as if it
were of a different type is not safe.

And even if, as is the case on many implementations, all pointers
happen to have the same representation, treating different pointer
types as if they were interchangeable tends to be logically
incorrect, even if you can get away with it.

The ORCdarrayfree function that the OP is trying to call expects
a void** argument. Presumably there's a good reason for that.
Or perhaps ORCdarrayfree itself is poorly designed. We don't
have enough information to know what the right solution is,
but we can be reasonably sure that passing an int** to something
expecting a void** isn't it.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
John
Guest
Posts: n/a
 
      01-06-2010
On Jan 6, 12:01*pm, Keith Thompson <(E-Mail Removed)> wrote:
> Ralph Malph <(E-Mail Removed)> writes:
> > John wrote:
> >> I wrote a function in C and compiled in gcc, I got a warning such as:

>
> >> ../test/test.c:26: warning: passing arg 1 of `ORCdarrayfree' from
> >> incompatib
> >> le pointer type

>
> >> Then I goto 26th line, I found the function ORCdarrayfree have a
> >> parameter with type void**,
> >> but I passed int** to it.

>
> >> So anyone can explain it for me and help me avoid this warning?

>
> > int** i;
> > void** v=(void**) i;

>
> [top-posting corrected]
>
> Using a cast to silence a warning is almost never the right thing
> to do.
>
> void* is a generic pointer type, in the sense that you can convert
> from any pointer type (excluding pointer-to-function types) to void*
> and back again without loss of information.
>
> There is no generic pointer-to-pointer type.
>
> I don't know what ORCdarrayfree, but apparently it requires an
> argument of type void**, most likely pointing to the first element
> of an array of void*. *The int** argument you're passing is probably
> a pointer to the first element of an array of int*. *void* and int*
> are distinct and incompatible types.
>
> You need to pass a valid void** value to ORCdarrayfree. *The question
> is how you can obtain such a value. *We can't guess at an answer
> without knowing more about ORCdarrayfree and what you're trying to
> pass to it.
>


ORCdarrayfree is used to free 2-d array allocated by malloc.
The src is:

/* ORCdarraynew function return void** ,
and ORCdarrayfree should get void** to
make these 2 functions to be used in
allocating integer, char, and other
customize type */

void**
ORCdarraynew (int row, int col, int size)
{
void **arr;

arr = (void **) malloc (sizeof(void *) * row + size * row * col);
if ( arr != NULL ) {
void *head;

head = (void *) arr + sizeof(void *) * row;
memset (arr, 0, sizeof(void *) * row + size * row * col);
while (row--) {
arr[row] = head + size * row * col;
}
}

return arr;
} /* End of ORCdarraynew*/

void
ORCdarrayfree (void **arr)
{
if ( arr != NULL ) {
free (arr);
arr = NULL;
}
} /* End of ORCdarrayfree*/


We can call them like:

int **p;
p = (int**)ORCdarraynew(nrows, ncols, sizeof(int));

ORCdarrayfree(p);

So the parameter of ORCdarrayfree will be converted from int** to
void**.
While, the gcc compiler give me a warning:

warning: passing arg 1 of `ORCdarrayfree' from
incompatib
le pointer type

So please help me.


 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      01-06-2010
John <(E-Mail Removed)> writes:
> On Jan 6, 12:01*pm, Keith Thompson <(E-Mail Removed)> wrote:

[...]
>> You need to pass a valid void** value to ORCdarrayfree. *The question
>> is how you can obtain such a value. *We can't guess at an answer
>> without knowing more about ORCdarrayfree and what you're trying to
>> pass to it.
>>

>
> ORCdarrayfree is used to free 2-d array allocated by malloc.
> The src is:
>
> /* ORCdarraynew function return void** ,
> and ORCdarrayfree should get void** to
> make these 2 functions to be used in
> allocating integer, char, and other
> customize type */
>
> void**
> ORCdarraynew (int row, int col, int size)


These should probably be size_t rather than int.

> {
> void **arr;
>
> arr = (void **) malloc (sizeof(void *) * row + size * row * col);


Casting the result of malloc is unnecessary and can mask errors.

> if ( arr != NULL ) {
> void *head;
>
> head = (void *) arr + sizeof(void *) * row;
> memset (arr, 0, sizeof(void *) * row + size * row * col);
> while (row--) {
> arr[row] = head + size * row * col;
> }
> }
>
> return arr;
> } /* End of ORCdarraynew*/


So you're allocating a chunk of memory consisting of an array of void*
pointers, immediately followed by a 2-dimensional array of some
arbitrary data, where each of the initial void* pointers points to a
row in the 2d array. Interesting. Let's call these two sections the
"index" and the "table", respectively.

You're making some non-portable assumptions, though.

The memset call zeros both the index and the table. The former is
useless, since you immediately initialize the table anyway. Zeroing
the table may or may not be sensiple, depending on what data you're
storing. Remember that null pointers aren't necessarily all-bits-zero
(though they commonly are).

You're also assuming that the table will be properly aligned.
Consider a system where void* is 32-bit aligned, double is 64-bit
aligned, and you want to allocate a table of doubles with an odd
number of rows.

> void
> ORCdarrayfree (void **arr)
> {
> if ( arr != NULL ) {
> free (arr);
> arr = NULL;
> }
> } /* End of ORCdarrayfree*/


Note that the "arr != NULL" test is unnecessary; free() does nothing
if you give it a null pointer argument. And setting arr to NULL is
useless; you're just clobbering a local object. You might want to do
"*arr = NULL;" -- or you might just want to leave it alone.

>
> We can call them like:
>
> int **p;
> p = (int**)ORCdarraynew(nrows, ncols, sizeof(int));
>
> ORCdarrayfree(p);
>
> So the parameter of ORCdarrayfree will be converted from int** to
> void**.
> While, the gcc compiler give me a warning:
>
> warning: passing arg 1 of `ORCdarrayfree' from
> incompatib
> le pointer type


gcc is correct; the pointer types are incompatible.

> So please help me.


I think you need to allocate the index and the table in two separate
calls to malloc().

Here's a thought. Allocate row+1 void* elements for the index.
Allocate size*row*col bytes for the table; using a separate call to
malloc guarantees proper alignment. Store the address of the table in
the 0th element of the index, then return the address of the 1st
element. ORCdarrayfree can then index backwards to obtain the address
of the table, free the table, then free the index.

I haven't completely thought this through. This approach should be
type-safe, but I think you might have some problems with indexing
(e.g., p[x][y]).

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      01-06-2010
pete <(E-Mail Removed)> writes:
> John wrote:

[...]
>> /* ORCdarraynew function return void** ,
>> and ORCdarrayfree should get void** to
>> make these 2 functions to be used in
>> allocating integer, char, and other
>> customize type */
>>
>> void**
>> ORCdarraynew (int row, int col, int size)
>> {

[...]
>> We can call them like:
>>
>> int **p;
>> p = (int**)ORCdarraynew(nrows, ncols, sizeof(int));
>>
>> ORCdarrayfree(p);

[...]
> Why don't you rewrite ORCdarraynew to return type (int**) instead?


Because it's intended to allocate a 2d array of any arbitrary type;
that's what the "size" parameter is for.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
 
 
Reply

Thread Tools

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 On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off




Advertisments