In most cases, using pointer arguments this way results in less readable
and maintainable code.
While this is true, I must respectfully disagree with most of the
rest of what you're saying.
It's not clear whether the callee will use the
existing values of the pointed-to objects or whether it will
unconditionally change them. When encountering such a function call,
you *must* study its definition, to see what exactly is happening.
....unless the pointer parameters have 'const' attached to them in
the right places, so you can tell they're not being changed. If
they're *not* constified, then it's almost always better to assume
they *will* be changed. (No guarantees, though.)
To be more clear, I'm talking about returning back scalar information to
s/returning back/returning/
the caller. It is perfectly OK to do it for arrays. So, in the case of
the OP, another valid solution would be
void randomise(int *array);
where the caller is passing the address of the first int in an array
of three int's.
I think this is worse than the original for *several* reasons.
void foo(int *bar);
is the accepted idiom for "bar is an array of int," with no constness
guarantees either way; it's rare IME to see
void foo(const int *bar);
So just by looking at the prototype, the client can't tell as reliably
whether the value of *bar will be changed.
void foo(const int bar[3]);
would be preferable in this case, since it specifies that we need to
pass exactly 3 integers in the array -- not 2, not 4, but 3. Doesn't
help the compiler, but it can help the client.
Finally, I think that the average programmer is likely to find the
array-based solution simply too clumsy. It takes time and LOC to
initialize an array that would be slightly less annoying to do with
single ints. Unless, of course, the parameters are part of a larger
"chunk" of information (say, the XYZ coordinates of a point), in
which case it probably makes more sense to pass around a (pointer to
a) 'struct'.
When I see
int a, b, c;
...
foo(&a, &b, &c);
it's pretty obvious that something is going to get changed inside
foo. In contrast, when I see
int r[3];
...
foo(r);
I can't even tell without checking types again that r *is* getting
"passed by pointer." I think that's more of a disadvantage than
whatever advantages you see to the lack of & operators -- I consider
&s a red flag!
Just for completeness, what do you think of
void foo(int (*bar)[3]);
int r[3];
...
foo(&r);
?
(I think it's unnecessarily ugly and restrictive, myself.)
-Arthur