0

I have a method in C that expects a double pointer as an argument:

void method(
    // in/out
    double *dOne,
    ...)

The caller has a float pointer

float *fOne;

What is a good way call method() with fOne?

method((double*)fOne, ...);

is not the best, is it?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Flippowitsch
  • 315
  • 3
  • 15
  • There are no methods in C. C only has functions. – Tom Karzes Mar 09 '16 at 08:23
  • 2
    Casting a `float*` to a `double*` will not work for this. Depending on what is really being done, perhaps: `double temp = *fOne; method(&temp,...);*fOne = temp;`. You could wrap that in a function named something like `void fmethod(float* pf);` – Michael Burr Mar 09 '16 at 08:24
  • If the function wants a `double *`, then you need to pass it a genuine `double *`. You can convert to/from `float` outside of the function. – Tom Karzes Mar 09 '16 at 08:24
  • 1
    It's easier to understand why this wont work if you know that typically a `float` is 32 bits of data, and `double` is 64 bits of data. If you have an array of, say, five `float` elements (that is 20 bytes), then casting that to `double *` will not create an array of five `double` elements (which would be 40 bytes). – Some programmer dude Mar 09 '16 at 08:26
  • Thanks to all. I think Michael Burr's comment is the answer. – Flippowitsch Mar 09 '16 at 09:39

1 Answers1

2

You should never cast pointers of different types. When the pointed-to types have different representations, such forced conversions simply don't make any sense. For example, double and float might not have the same size or representation, in which case pointer conversions between the two types are blatantly incorrect.

But even if you know that the different types have the same representation, the pointer conversion is still not safe! Because of the strict aliasing rule, such conversions might yield incorrectly generated code by the compiler, since the compiler is free to assume that you would never access the given data through a pointer of an incorrect type. So it might optimize away portions of your code.

It is only safe to cast any given pointer:

  • To/from a pointer pointing at the same qualified type (*).
  • To a pointer pointing at the same type, but with more qualifiers specified (*).
  • To/from void pointer.
  • To a null pointer.
  • To a pointer to byte integer types, such as char* or uint8_t*.

All other cases of pointer to pointer conversions are bugs and invoke undefined behavior as soon as you access the pointed-to data. Including casts from char* to a pointer to a larger type.


(*) Qualified type means, a type with qualifiers such as const or volatile present. For example it is safe to convert from int* to const int* but never the other way around.

Community
  • 1
  • 1
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Note that is also "safe" (in the sense that you mean) to cast *back* from a `char *` to the original type. – Oliver Charlesworth Mar 09 '16 at 08:59
  • @OliverCharlesworth Well... it is safe to convert from for example `int*` to `bananas*` and then back to `int*`, without ever accessing the data through the `bananas` pointer. Why you would do that though, I have no idea. – Lundin Mar 09 '16 at 09:02
  • Well in the `char *` case, the cast to `char *` is explicitly allowed in order to do byte-by-byte operations. But at some point you need to get back to the original type, which is also safe! – Oliver Charlesworth Mar 09 '16 at 09:04
  • @OliverCharlesworth Well... yes... no... maybe :) It is safe if you don't modify the pointed-at address. But if you do, whether it is safe or dangerous depends on alignment. – Lundin Mar 09 '16 at 09:14