7

This is an exercise from C++ Primer 5th edition, which goes:

Exercise 6.24: Explain the behavior of the following function. If there are problems in the code, explain what they are and how you might fix them.

void print(const int ia[10])
{
    for (size_t i = 0; i != 10; ++i)
        cout << ia[i] << endl;
}

I can not find any problem in the codes. What is the point of this exercise?

pezy
  • 902
  • 2
  • 6
  • 27
  • 1
    It's not a very useful function. It can only print an array of exactly 10 elements. If you provide an array of less than 10 elements, it will break. – Neil Kirk Oct 23 '14 at 14:41
  • @NeilKirk: What if you provide an array of more than 10 elements? – Kerrek SB Oct 23 '14 at 14:42
  • I know the magic numbers already. anything else? – pezy Oct 23 '14 at 14:42
  • The parameter is just a pointer, equivalent to `const int*`. You can pass a pointer to a smaller array, or to a single object, or a null pointer. The function will go wrong if you do any of these. – Mike Seymour Oct 23 '14 at 14:42
  • 1
    To my understanding, if called with `ia` having more than 10 elements, only the first 10 will be printed. – Codor Oct 23 '14 at 14:42
  • @KerrekSB True. At least it won't explode. – Neil Kirk Oct 23 '14 at 14:50

1 Answers1

10

The general problem is that in C++ declaration syntax, array types in function parameter declarations mean something non-intuitive: A parameter declared as T[] or as T[10] or as T[1279] is actually declared as T* – all these parameter declarations are identical.*

Remember that there are no prvalues of array type in C++, and so array types cannot be function parameter or return types. (When used as a prvalue, an array decays to a pointer to its first element.)

Therefore, your function declaration is actually (with T = const int):

void print(const int *);

This parameter type plays well with the array-to-pointer decay, but it is now clear that you can pass any pointer to int to this function, and the correctness of the function execution cannot be determined from the function definition alone.

*) It's a bit more complicated in C99.


On a side note, array glvalues are perfectly fine, as is the following function which has a parameter whose type is "reference to array":

void print10(const int (&a)[10])
{
    for (auto i : a) { std::cout << i << "\n"; }
}
Community
  • 1
  • 1
Kerrek SB
  • 428,875
  • 83
  • 813
  • 1,025
  • @pezy I have the same book as you, so I know glvalues won't have been discussed yet. [This answer](http://stackoverflow.com/a/3601661/729541) will give you an idea of what they are, if you've not encountered them elsewhere before. – John H Oct 23 '14 at 14:56
  • That's a feature that should have been deprecated a long time ago. – Mark Ransom Oct 23 '14 at 14:57
  • 1
    "no rvalues of array type in C++, and so array types cannot be function parameter or return types." Thx for your reminder!! – pezy Oct 23 '14 at 14:59
  • @MarkRansom: You first have to make sure every textbook in the world teaches `int main(int argc, char **argv)` and not `char* argv[]`. Oh, don't forget to change the official C standard while you're at it. Like it or not, array-syntax-to-define-pointer-arguments is widely used in new code. – Ben Voigt Oct 23 '14 at 14:59
  • @BenVoigt there are other features of C that have disappeared over time, this should have been included. If it had happened 15 years ago nobody would be missing it today. – Mark Ransom Oct 23 '14 at 15:05
  • 1
    While the answer is perfectly correct, I'm not sure that explaining something in terms of prvalues and glvalues to someone reading a primer will help much. Especially as the primer was written before C++11, and these terms were introduced in C++11. – James Kanze Oct 23 '14 at 15:09
  • There's a question on SO (where else?) about [What are rvalues, lvalues, xvalues, glvalues, and prvalues?](http://stackoverflow.com/questions/3601602/what-are-rvalues-lvalues-xvalues-glvalues-and-prvalues) where there are comments and answers that include a number of external references too. – Jonathan Leffler Oct 23 '14 at 15:11
  • @JamesKanze: Yes, I think it would benefit from using saying "references to arrays are perfectly fine (these are *glvalues*)" or similar. – Ben Voigt Oct 23 '14 at 15:22
  • @MarkRansom: I don't disagree. But it didn't start phasing out 15 years ago, so it can't be deprecated yet. On the other hand it might be possible to push through a revision request to both Standards bodies to remove the `[]` notation from all examples, leave the syntax of `T[]` defined for function parameters but add a footnote that `T*` is preferred. That lays the foundation for putting pressure on books and tutorials to change their examples... and a Standard rev a few years down the line could then change `T[]` in function parameters to *diagnostic-required*. – Ben Voigt Oct 23 '14 at 15:28
  • 1
    @BenVoigt, James: Well, yes, I agree that this isn't exactly "beginner level", but I can't think of a way that's easier and also correct. I think the correct answer has merit in the long run as more people come by and read it, though it may not be the most easily accessible one. I'd hate to say "references are glvalues", because that's just not true. The word "reference" can pertain either to a variable or a type, but never to a value. I'd rather not want anyone to *unlearn* things later that they learned earlier. – Kerrek SB Oct 23 '14 at 19:34
  • "function parameters which are references to arrays are perfectly fine" – Ben Voigt Oct 23 '14 at 20:17