As you understand the error: it is impossible to convert from 'int []' to 'int []'

When compiling the following code:

void DoSomething(int Numbers[]) { int SomeArray[] = Numbers; } 

VS2005 compiler complains about error C2440: 'initializing': cannot convert from 'int []' to 'int []'

I understand that it is actually trying to point to an array pointer that will not work. But how do you explain the error to someone who is learning C ++?

+4
source share
5 answers

There are three things you need to explain to the person you are trying to help:

  • Arrays cannot be passed by function value in C ++. To do what you are trying to do, you need to pass the address of the beginning of the array to DoSomething() , as well as the size of the array in a separate int argument (well, size_t , but I would not argue). You can get the start address of some myArray with the expression &(myArray[0]) . Since this is such a general thing that needs to be done, C ++ only allows the use of an array name - for example. myArray - get the address of its first element. (Which may be useful or confusing, depending on how you look at it.) To make things even more confusing, C ++ allows you to specify the type of array (for example, int Numbers[] ) as a function parameter, but in secret it treats this parameter as if it were declared as a pointer ( int *Numbers in this case) - you can even make Numbers += 5 inside DoSomething() so that it points to the array, starting from the sixth position!

  • When you declare an array variable, such as SomeArray in C ++, you must either provide an explicit size or an “initialization list” , which is a list of values ​​separated by commas between curly braces. It is not possible for the compiler to infer the size of the array based on another array that you are trying to initialize, because ...

  • You cannot copy one array to another or initialize one array from another in C ++. So even if the Numbers parameter was really an array (for example, size 1000) and not a pointer, and you specified the size of SomeArray (again, as they say 1000), the string int SomeArray[1000] = Numbers; would be illegal.


To do what you want to do in DoSomething() , first ask yourself:

  • Do I need to change any values ​​in Numbers ?
  • If so, do I want to prevent callers from seeing these changes?

If the answer to any question is “No,” you actually do not need to make a copy of Numbers in the first place - just use it as is and forget about creating a separate SomeArray array.

If the answer to both questions is “Yes”, you will need to make a copy of Numbers in SomeArray and work on it. In this case, you should make SomeArray C ++ vector<int> instead of another array, as that really simplifies. (Explain the advantages of vectors over manual allocation of dynamic memory, including the facts that they can be initialized from other arrays or vectors, and if necessary they will call element constructors, unlike C-style memcpy() .)

+5
source

Say there are types and incomplete types:

 struct A; 

It is an incomplete type of structure called A. Although

 struct A { }; 

It is a complete type of structure named A. The size of the first is unknown, and the size of the second is known.

Incomplete types of classes exist, similar to the structure described above. But there are also incomplete array types:

 typedef int A[]; 

This is an incomplete type of array called A. Its size is not yet known. You cannot create an array from it because the compiler does not know how large the array is. But you can use it to create an array only if you initialize it immediately:

 A SomeArray = { 1, 2, 3 }; 

Now the compiler knows that the array is an int array with 3 elements. If you try to initialize the array with a pointer, the compiler will not be smarter than before and will refuse because it will not give the size of the array that will be created.

+12
source

When trying to make the error message more useful, the compiler actually confuses things. Despite the fact that the Numbers parameter is declared as an array, C / C ++ does not actually pass (cannot) the array - the Numbers parameter is actually a pointer.

So the error really should say "cannot convert from 'int *' to 'int []'"

But then there will be confusion - "hey, there are no int* involved in the expression," someone might say.

For this reason, it is better to avoid array parameters - declare them as pointers, since this is what you really get. And the explanation to someone who teaches C / C ++ should educate them that array parameters are fiction - they are really pointers.

+8
source

When I try to explain something, I always try to go down to the lowest level and build up from there. That they love to learn things, and I believe that people are more comfortable if you start with the basics that they know and build on from there.

In this case, I would probably start with something like:

The compiler is trying to do because you wrote an assignment operation. In C ++, you cannot directly assign an array because it does not have a built-in operator assignment (of any kind, only initializer and indexing are supported for arrays). Since C ++ supports overloaded operators for types, the compiler then searches for the overloaded assignment operator for the type "assigned", which takes the "assigned-from" type as an argument. Since there is also no overloaded operator for int [] that takes int [] as an argument, compiler errors are in the string, and errors tell you why the compiler cannot process the string.

Yes, this is probably too complicated, just saying something about knowing the size, incomplete types, etc. I also understand that it is also not complete (for example: the purpose of the initializer and the normal purpose, etc. are not discussed). However, my goal, as a rule, is to attract people to where they can independently determine the next answer, and for this you usually want to lay out a thought process to get an answer.

+4
source

Perhaps your answer might be: "Because the compiler does not know how large the array is."

Your example could work if there were explicit array sizes (perhaps with a typedef for clarity), and then you can explain pointers when introducing distributions of variable sizes.

+3
source

All Articles