3 ms·
One big difference is the rules on pointers. In C, if you write code like this: void dostufftotwoarrays(int* a, int* b); Then maybe b is equal to a + 3, so
by CJefferson 10y ago
One big difference is the rules on pointers.
In C, if you write code like this:
void dostufftotwoarrays(int* a, int* b);
Then maybe b is equal to a + 3, so your compiled code has to assume whenever it writes to an element of a, it might have changed an element of b, and so reload b from memory. Alternatively, it can do a bunch of tests at the start of the function, and compile multiple copies of the function for different situations.
In FORTRAN, this isn't possible (you don't tend to pass around raw pointers), so it is much easier for the compiler to reason about what objects might be in the same place, and which aren't.
The restrict keyword goes some way to fixing this in C, but is tricky yo use correctly, and also doesn't solve all problems.
- bmh100 10y agoWhat makes it tricky to use, and where does it fall short?
- CJefferson 10y agoThere are some weird rules, like: mypair* restrict position = &object->pair; float* restrict position_x = &position->x; Is undefined behaviour, as you can't take a restricted pointer to a child of a restricted pointer in the same scope (the rule isn't quite that simple, but that's part of it). In general, rules about pointers to pointers get complicated, and I've had trouble with them in the past. In general, it's a good idea to try to only use restrict for "leaf" pointers, not intermediate objects, but that does block some optimisations. There is also the obvious problem of people getting carried away, and marking something 'restrict' where they shouldn't have. While 'restrict' is very easy to use on simple structures (like just int*), if you look around you'll find very little, if any, material about using it for complicated nested data structures.
- Someone 10y agoThere's also the fact that restrict is only a promise to the compiler "this function will not be called with aliased arguments", not also a command "do not allow people to call this function with aliased arguments". As far as I know Fortran, at least in its original form, enforced the latter (that was fairly easy to do, as it didn't have dynamic memory allocation, pointers or recursion (the compiler determined the location in memory of all variables))
- greglindahl 10y agoNeither of your options is the actual rule. The actual rule is that when the program runs, there can't be any runtime aliasing. You can totally call a subroutine with several arguments being the same thing, as long as you don't do anything bad inside the subroutine. I'm aware of this because I tried to get the PathScale compiler team to add a warning for incorrect aliasing. That wasn't possible. But I did get a flag which made the compiler obey C aliasing rules for Fortran, and it was part of the "got the wrong answer? run with these flags and if you get the correct answer, your program is not standard-conforming" thingie.
- Someone 10y agoPlease educate me and explain how that contradict anything I claimed, as I don't see it. I claim it is only a promise, you claim you can call it with identical arguments. I don't see a contradiction; making a promise isn't the same as keeping it. Similarly, your argument that it is fine to break that promise as long as you don't do anything bad inside the subroutine, I read as "you sometimes can get away with breaking a promise", but again, that's not the same as not making the promise. What am I missing?
- CJefferson 10y agoThe difference is subtle. Here is a (stupid) example: int chooseone(restrict int* a, restrict int* b, bool c) { if(c) return *a; else return *b; } Here, we can pass the same pointer for a and b, because only one of them is ever accessed in any call to the function.
- Someone 10y agoThanks. I reread http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf, and initially didn't get that from the informal description of restrict given there. It says (section 6.7.3): "An object that is accessed through a restrict-qualified pointer has a special association with that pointer. This association, defined in 6.7.3.1 below, requires that all accesses to that object use, directly or indirectly, the value of that particular pointer." So, it hinges on the meaning of 'accesses'; it is a runtime thing, not a compile-time thing.
- greglindahl 10y agoYour Fortran summary is incorrect. F77-style arrays are generally passed as a raw pointer (under the hood.) F90-style allocatable arrays are passed as an array descriptor containing size information, again under the hood. This doesn't affect aliasing in Fortran at all. Aliasing is simply prohibited, which leaves the compiler free to generate code that gets the wrong answer, if the programmer screws up and has actual aliasing at run-time.
- CJefferson 10y agoApologises, you are right. It's so long since I did Fortran I had misremembered that the language made it impossible to alias, as opposed to it being undefined behaviour.