1

How to cast "ptr" to assign directly a zend_long into it without writing two lines?

zend_long *val = *ptr;
*val = *(ISC_LONG*)var->sqldata;
Marcodor
  • 4,578
  • 1
  • 20
  • 24
  • it comes as a funstion argument as: "char **ptr" in fact it is just a storrage buffer – Marcodor Jan 02 '17 at 11:57
  • 1
    Unless they are _compatible types_, this invokes undefined behaviour. – too honest for this site Jan 02 '17 at 12:13
  • Why can't you write 2 lines? Too readable? – Lundin Jan 02 '17 at 14:43
  • @Lundin, i think it will not allocate a local variable if i'll using cast on the fly – Marcodor Jan 02 '17 at 17:37
  • @Marcodor Whether or not local variables are allocated has nothing to do with the amount of lines or the presence/absence of programmer-declared variables. Either the results need to be stored at a temporary location or they don't - the compiler will/won't generate machine code for that regardless of what variables we do or don't declare in the C source. In this case the compiler will optimize away the local variable. It is generally good programming practice to split complex instructions into several lines by using temporary variables. – Lundin Jan 03 '17 at 07:46

2 Answers2

3

Assuming that your original code is correct, the corresponding assignment looks like this:

*((zend_long*)*ptr) = *(ISC_LONG*)var->sqldata;
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • This will most likely invoke undefined behavior because of strict aliasing violation. Unless `zend_long` happens to be type compatible with `ISC_LONG`. – Lundin Jan 02 '17 at 14:43
  • @Lundin That's right. This is why I wrote that the above will work only if the original code is correct. – Sergey Kalinichenko Jan 02 '17 at 14:47
0

Pointer casts like these are not well-defined behavior in C, unless the two structs happen to be compatible types. That is, they have to have identical members in identical order.

If they don't have that, then there is unfortunately no easy way to do this in C. If you somehow managed to get it to "work" it is merely out of luck - your code could crash at any time because of undefined behavior.

This is because such casts violate the so-called strict aliasing rule. You will have to dodge that rule by for example wrapping the structs inside a union type.

Community
  • 1
  • 1
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Thanks for useful info. I don't like over-casting too. But this is "enforced" in this case. ISC_LONG defined here: https://github.com/FirebirdSQL/firebird/blob/c6d9135586fde54b52e5c26f74d5dfd20c188f3f/src/include/types_pub.h#L111 and zend_long have almost the same definition in PHP source. So assigning by value should be safe. – Marcodor Jan 02 '17 at 17:43
  • @Marcodor If they are integer types of the same size you are fine. If they are of different sizes, or if they are structs, you would have problems. – Lundin Jan 03 '17 at 07:59