3 ms·
It gets even funnier in OCaml where they nominally defined it UB in order to get the freedom to make the only existing implementation always 100% reliably evalu
by qb45 10y ago
It gets even funnier in OCaml where they nominally defined it UB in order to get the freedom to make the only existing implementation always 100% reliably evaluate right-to-left, which reportedly was better for performance or something :)
And before somebody wonders about currying and eager evaluation, the problem is not functions but type constructors, which aren't curried.
- ufo 10y agoThe ocaml one is very annoying because the bytecode interpreter reliably evaluates arguments left-to-right but when you compile to native code it reliably evaluates right-to-left (or the other way around, I don't remember).
- deleted 10y ago[deleted]
- afrisch 10y agoI don't think so. Both bytecode and native evaluate right-to-left.
- ufo 10y agoI swear that I remember having programs that could behave differently in the bytecode and native compiler. Perhaps I'm remembering an older version of the compiler or another order-of-evaluation issue other than function parameters?
- gravypod 10y agoThe functions arguments are pushed onto the stack. From within the function you can think of the stack as an array. void test(a, b, c) stack[0] == a stack[1] == b stack[2] == c But to get the items in the stack in that order you have to... puch c push b push a If you wanted to do that, and still allow for left to right evaluation you could... temp_a = a temp_b = b temp_c = c push c puch b push a That would be 2x instructions for every (already expensive at that time) function call. Defining unordered evaluation as UB was to avoid having to do temp_a, temp_b, temp_c. Now compiles can do that and trivially optimize that sort of thing out.
- jacquesm 10y agoExcept that in most cases that's not how it is done. Instead, the stackframe is created in one go with a single change to the stack pointer and then the values are filled in in whatever order the compiler / language desires. Here is a typical example using GCC: movq %rsp, %rbp subq $16, %rsp movl $12, -4(%rbp) addl $1, -4(%rbp) movl -4(%rbp), %eax movl $14, %edx movl %eax, %esi movl $12, %edi call f Which moves the parameters using registers (subject to availability) as a further optimization. The 'subq' reserves space for the stackframe with addresses relative to rbp being the parameters.