0

Suppose we have a function which takes double pointer as an argument and we want to modify that value:

void fun(uint8_t *arg1) {
    *arg1 = 2;
}

int main(void) {
    double a;
    fun((uint8_t*)&a); // does not work

    return 0;
}

Is this even possible?

c0dehunter
  • 6,412
  • 16
  • 77
  • 139

4 Answers4

1

What you are specifying is undefined behaviour: you can't cast the pointer to a different type.

Your best bet is to create a uint8_t in main, pass a pointer to that to your function fun, then assign that modified value to the double.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • "you can't cast the pointer to a different type" - except the void pointers. – c0dehunter Aug 18 '14 at 10:50
  • Sure you can cast pointers, as long as they are correctly aligned. `uint8_t *` always is, so this is safe. The assignment in `fun` also is fine (I'm not 100% sure, though, if strict aliasing is a problem, that is, if `uint8_t` is a character type in this context). Reading `a` after the assignment _might_ be undefined, if (and only if) the result is a trap representation. – mafso Aug 18 '14 at 11:21
  • OK, additionally, `a` should be initialized to assign some values to the remaining bytes of the `double` value, but only to be able to _read_ `a`. – mafso Aug 18 '14 at 11:29
  • Excepting `void*`, *any* unrelated cast is undefined behaviour so your "so this is safe" guarantee is fallacious. It might be safe, but the compiler does not need to guarantee that. – Bathsheba Aug 18 '14 at 12:30
  • C11 (draft) 6.3.2.3 p.11 _A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned [omitted footnote] for the referenced type, the behavior is undefined. Otherwise, when converted back again, the result shall compare equal to the original pointer. When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object. Successive increments of the result, up to the size of the object, yield pointers to the remaining bytes of the object._ – mafso Aug 18 '14 at 13:13
  • According to [this](http://stackoverflow.com/a/16138470/1741125), strict aliasing _is_ a problem (to add to my comment above), `uint8_t` is not a character type, at least in theory. A comment under the linked answer says there was some discussion on the gcc mailing list to use this for type-based aliasing analysis, but it was considered to be better not to treat it differently than the character types. So, there is UB, strictly speaking, but not for the reasons you gave (and apparently not on current implementations, at least not on gcc). – mafso Aug 18 '14 at 13:49
1

Simplest solution is to use temporary variable:

double a;
uint8_t b = a;
fun(&b);

Another solution is to use void* and tell used type with another parameter:

void fun(void *arg1, int type) {
    switch(type)
        case TYPE_DOUBLE:
            *(double*)arg1 = 2;
            break;
        case TYPE_UINT8:
            *(uint8_t*)arg1 = 2;
            break;
     }
 }
user694733
  • 15,208
  • 2
  • 42
  • 68
1
void fun(uint8_t *arg1) {
    double a = 2;
    memcpy(arg1, &a, sizeof a);
}
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70
1

Typecast the variablearg1 inside fun as like this *(double *)arg1 = 2;

mahendiran.b
  • 1,315
  • 7
  • 13