4 ms·
> Given that the size of a Point is 12 bytes, the reference to the z members of points is turned into points + (12 * i + 8). No, it's not. In the C abstrac
by wnoise 10y ago
> Given that the size of a Point is 12 bytes, the reference to the z members of points is turned into points + (12 * i + 8).
No, it's not. In the C abstract machine, arithmetic on pointers is not the same as arithmetic on integers.
This really is "points + i", but on pointers to an object with sizeof 12, and then a dereference with an offset of 8. These pointers don't have the overflow undefined behavior (but do have other undefined behavior if you have a pointer outside a C object). As implemented in assembly, yes, it comes to a multiplying by 12, but that's not a C int at that point. (And can be done with addressing trickery, as the article says.)
- kevinnk 10y agoPerhaps someone who has a better grasp of the standard can correct me, but as far as I can tell, your interpretation is correct and the given example is not undefined behavior. From 6.5.2.1 (Array Subscripting) of the C11 draft: "A postfix expression followed by an expression in square brackets [] is a subscripted designation of an element of an array object. The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))). Because of the conversion rules that apply to the binary + operator, if E1 is an array object (equivalently, a pointer to the initial element of an array object) and E2 is an integer, E1[E2] designates the E2-th element of E1 (counting from zero)." From 6.5.6 (Additive Operators): "When an expression that has integer type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integer expression. [...] If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined." To me, those sections together read that there should be no overflow as long as i is smaller than the length of `points` + 1, and thus no undefined behavior. Does anyone have another interpretation?
- comex 10y agoNope, you're correct. On the other hand, earlier today I read a post about a pretty similar-seeming phenomenon (signed overflow UB reducing the number of lea instructions that have to be generated): https://gist.github.com/rygorous/e0f055bfb74e3d5f0af20690759de5a7 https://gist.github.com/rygorous/e0f055bfb74e3d5f0af20690759... Perhaps the author had heard that -fwrapv causes extra 'lea's but got mixed up as to why. (TL;DR: it makes it harder for the compiler to prove that you're not a sadist using negative array indices.)
- agl 10y agoI was talking about the addressing at the assembly level, because that's what LEA and addressing modes deal with. However, your references to a spec make a very good point. Maybe I misunderstood Chandler in the first place. I've pulled the post (since it may be incorrect) until I can sort it out with a compiler person.
- TorKlingberg 10y agoI think when the author writes points + (12 * i + 8), it is meant to be a calculation as done in assembly, not in C.
- wnoise 10y agoSure, but at that point what relationship does it have to the semantics of C ints?