[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c

Casting one pointer type to another

Francogrex

3/23/2011 11:15:00 AM

Hi, how to I get this correctly? I am trying to cast the double
pointer a_double_ptr to an int pointer a_int_ptr. What I need is to
have the a_int_ptr dereferenced to 15. but it's not, it's
dereferencing to -858993459. I am sure I am doing something very wrong
but can't know how to fix it. Thanks. Code below.

int main ()
{
double a=15.65;
double* a_double_ptr = &a;
int* a_int_ptr= (int *) a_double_ptr;
return 0;
}

GDB:
(gdb) p a
$1 = 15.65
(gdb) p &a
$2 = (double *) 0x22ff40
(gdb) p &a_double_ptr
$3 = (double **) 0x22ff4c
(gdb) p a_double_ptr
$4 = (double *) 0x22ff40
(gdb) p *a_double_ptr
$5 = 15.65
(gdb) p &a_int_ptr
$6 = (int **) 0x22ff48
(gdb) p a_int_ptr
$7 = (int *) 0x22ff40
(gdb) p *a_int_ptr
$8 = -858993459
7 Answers

Mark Bluemel

3/23/2011 11:40:00 AM

0

On 03/23/2011 11:14 AM, Francogrex wrote:
> Hi, how to I get this correctly? I am trying to cast the double
> pointer a_double_ptr to an int pointer a_int_ptr. What I need is to
> have the a_int_ptr dereferenced to 15. but it's not,

No it wouldn't be.

> it's
> dereferencing to -858993459. I am sure I am doing something very wrong

You think so?

> but can't know how to fix it. Thanks. Code below.
>
> int main ()
> {
> double a=15.65;
> double* a_double_ptr =&a;
> int* a_int_ptr= (int *) a_double_ptr;

So here you are saying go to the address stored in a_double_ptr,
and interpret the bit pattern there as if it were the representation
of an int. Why do you expect that to work?

What are you really trying to do here? Your sample is so lacking in
context as to be meaningless.

The obvious thing to do is something like "int b = *a_double_ptr;",
but I suspect your real use-case is more subtle. Tell us more about
what you are trying to achieve, preferably with some more meaningful
example code, and we may be able to help more.

Eric Sosman

3/23/2011 11:47:00 AM

0

On 3/23/2011 7:14 AM, Francogrex wrote:
> Hi, how to I get this correctly? I am trying to cast the double
> pointer a_double_ptr to an int pointer a_int_ptr. What I need is to
> have the a_int_ptr dereferenced to 15. but it's not, it's
> dereferencing to -858993459. I am sure I am doing something very wrong
> but can't know how to fix it. Thanks. Code below.
>
> int main ()
> {
> double a=15.65;
> double* a_double_ptr =&a;
> int* a_int_ptr= (int *) a_double_ptr;
> return 0;
> }
>
> GDB:
> (gdb) p a
> $1 = 15.65
> (gdb) p&a
> $2 = (double *) 0x22ff40
> (gdb) p&a_double_ptr
> $3 = (double **) 0x22ff4c
> (gdb) p a_double_ptr
> $4 = (double *) 0x22ff40
> (gdb) p *a_double_ptr
> $5 = 15.65
> (gdb) p&a_int_ptr
> $6 = (int **) 0x22ff48
> (gdb) p a_int_ptr
> $7 = (int *) 0x22ff40
> (gdb) p *a_int_ptr
> $8 = -858993459

To get the int value 15 from the double value 15.65, you must
convert the double to an int. Working directly with the variables

double a = 15.65;
int x = a;

Or, working with pointers

double a = 15.65;
double* a_double_ptr = &a;
int x = *a_double_ptr;

Or, working entirely through pointers

double a = 15.65;
double* a_double_ptr = &a;
int x;
int* a_int_ptr = (int*)a_double_ptr;
*a_int_ptr = *a_double_ptr;

What your code does is quite different: It produces an int*
that points to the memory holding a. When you use that int* to
inspect a's memory, no conversion takes place; the system just
interprets a's memory, or part of it, as if an int value were
stored there, and winds up with garbage. (By the way, even this
much isn't guaranteed; something even stranger than winding up
with garbage could occur. You have done a form of "type punning"
whose effect the language does not actually define, and all bets
are off -- the effect you see is a common outcome, but not the
only possibility.)

Have you ever read "The Lady or the Tiger?" Imagine yourself
as the condemned man in the arena, but facing only one door. Behind
that door is a tiger named "a", and a sign on the door says "tiger,"
spelled "a_double_ptr". You cleverly cover the sign with another
that says "lady," spelled "a_int_ptr" -- but changing the sign doesn't
alter what you'll find when the door opens.

--
Eric Sosman
esosman@ieee-dot-org.invalid

Eric Sosman

3/23/2011 11:53:00 AM

0

On 3/23/2011 7:46 AM, Eric Sosman wrote:
> [...]
> Or, working entirely through pointers
>
> double a = 15.65;
> double* a_double_ptr = &a;
> int x;
> int* a_int_ptr = (int*)a_double_ptr;

Ooops! Should have been `int* a_int_ptr = &x;'. As it
stands, I've just repeated your mistake.

> *a_int_ptr = *a_double_ptr;

--
Eric Sosman
esosman@ieee-dot-org.invalid

Francogrex

3/23/2011 12:12:00 PM

0

On Mar 23, 12:40 pm, Mark Bluemel <mark_blue...@pobox.com>
> what you are trying to achieve, preferably with some more meaningful
> example code, and we may be able to help more.

ok I don't know if you're prepared for this, here is what I'm really
trying to do. I have a fortran function that starts like this:
FUNCTION AKSCDF (M,N,D,U)
DIMENSION U(N)
K = FLOAT (M * N) * D + 0.5
U(1) = 1.0
.... etc
M, N are integers, D would be the equivalent of a float and U would be
an array of floats
The C wrapper around it that works correctly is this:
void akscdf_(int*, int*, float *, float *);
This is compiled to a dynamic library.

Now the tricky part, there is an external application that accesses
the dynamic library (so it accesses the fortran code through the c
wrapper) but it can't send its arguments as int* or float*, it can
only handle double*. Hence the reason I wanted to write a code on top
of the C wrapper like this:
Fix_akscdf_(double*, double*, double*, double*)
{
akscdf_((double*)int*, (double*) int*, (double*)float*,
(double*)float*)
....etc. Obviously the casting as done above is bad and I'm looking for
a good way.

Ben Bacarisse

3/23/2011 12:41:00 PM

0

Francogrex <franco@grex.org> writes:

> On Mar 23, 12:40 pm, Mark Bluemel <mark_blue...@pobox.com>
>> what you are trying to achieve, preferably with some more meaningful
>> example code, and we may be able to help more.
>
> ok I don't know if you're prepared for this,

It's not that peculiar a situation.

> here is what I'm really
> trying to do. I have a fortran function that starts like this:
> FUNCTION AKSCDF (M,N,D,U)
> DIMENSION U(N)
> K = FLOAT (M * N) * D + 0.5
> U(1) = 1.0
> ... etc
> M, N are integers, D would be the equivalent of a float and U would be
> an array of floats
> The C wrapper around it that works correctly is this:
> void akscdf_(int*, int*, float *, float *);
> This is compiled to a dynamic library.
>
> Now the tricky part, there is an external application that accesses
> the dynamic library (so it accesses the fortran code through the c
> wrapper) but it can't send its arguments as int* or float*, it can
> only handle double*.
>
> Hence the reason I wanted to write a code on top
> of the C wrapper like this:
> Fix_akscdf_(double*, double*, double*, double*)

Do these first three have to be pointers? It will simplify matters if
the wrapper round the wrapper can be passed M, N and D directly. For
example, if Fix_akscdf_ is called only from C and AKSCDF does not alter
M, N or D you don't need the pointers.

> {
> akscdf_((double*)int*, (double*) int*, (double*)float*,
> (double*)float*)
> ...etc. Obviously the casting as done above is bad and I'm looking for
> a good way.

As it stands, you need to copy the values into variables of the right
type (which will do the conversion) and pass pointers to these copies.
You then need to copy the values back out for those variables that the
function might have changed.

The conversion could be done like this in C99:

void Fix_akscdf_(double *mp, double *np, double *dp, double *up)
{
int m = *mp, n = *np;
float d = *dp;
float u[n];
for (int i = 0; i < n; i++)
u[i] = up[i];
akscdf_(&m, &n, &d, u);
/* skip this if akscdf_ does not change the array */
for (int i = 0; i < n; i++)
up[i] = u[i];
/* skip this if akscdf_ does not change m, n or d */
*mp = m;
*np = n;
*dp = d;
}

If you can't use variably modified arrays (a C99 feature) you will need
to allocate the array using malloc and free it using free.

The cost of the copy might be quote high (how big is the array in a
typical call?) and so you might have to re-think this design. Maybe the
Fortran code an be re-written, maybe the calling code can be persuaded
to use a float array, and so on.

--
Ben.

Kenneth Brody

3/23/2011 1:39:00 PM

0

On 3/23/2011 7:46 AM, Eric Sosman wrote:
> On 3/23/2011 7:14 AM, Francogrex wrote:
[...]
>> int main ()
>> {
>> double a=15.65;
>> double* a_double_ptr =&a;
>> int* a_int_ptr= (int *) a_double_ptr;
>> return 0;
>> }
[...]
> Have you ever read "The Lady or the Tiger?" Imagine yourself
> as the condemned man in the arena, but facing only one door. Behind
> that door is a tiger named "a", and a sign on the door says "tiger,"
> spelled "a_double_ptr". You cleverly cover the sign with another
> that says "lady," spelled "a_int_ptr" -- but changing the sign doesn't
> alter what you'll find when the door opens.

I like your analogy. It gives a clear mental picture of what's going on,
while avoiding things like "IEEE", "two's complement", and "bit patterns".

On the other hand, it also brings to my mind a picture of the transmogrifier
from "Calvin and Hobbes". Hmm... GIYF...

uggc://zrzoref.funj.pn/arjfbat/pnyiva.ugzy

--
Kenneth Brody

Francogrex

3/24/2011 11:48:00 AM

0

On Mar 23, 1:41 pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> The conversion could be done like this in C99:
>
>   void Fix_akscdf_(double *mp, double *np, double *dp, double *up)
>   {
>       int m = *mp, n = *np;
>       float d = *dp;
>       float u[n];
>       for (int i = 0; i < n; i++)
>           u[i] = up[i];
>       akscdf_(&m, &n, &d, u);
>       /* skip this if akscdf_ does not change the array */
>       for (int i = 0; i < n; i++)
>           up[i] = u[i];
>       /* skip this if akscdf_ does not change m, n or d */
>       *mp = m;
>       *np = n;
>       *dp = d;
>   }
>
> If you can't use variably modified arrays (a C99 feature) you will need
> to allocate the array using malloc and free it using free.
>
> The cost of the copy might be quote high (how big is the array in a
> typical call?) and so you might have to re-think this design.  Maybe the
> Fortran code an be re-written, maybe the calling code can be persuaded
> to use a float array, and so on.

Thanks Ben. It worked! With your help and also with the suggestion of
Eric above as well. Regards.