Casting one pointer type to another

F

Francogrex

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
 
M

Mark Bluemel

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.
 
E

Eric Sosman

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.
 
E

Eric Sosman

[...]
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.
 
F

Francogrex

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.
 
B

Ben Bacarisse

Francogrex said:
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 = up;
akscdf_(&m, &n, &d, u);
/* skip this if akscdf_ does not change the array */
for (int i = 0; i < n; i++)
up = u;
/* 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.
 
F

Francogrex

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 = up;
      akscdf_(&m, &n, &d, u);
      /* skip this if akscdf_ does not change the array */
      for (int i = 0; i < n; i++)
          up = u;
      /* 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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top