오류를 이해하는 방법 : 'int []'에서 'int []로 변환 할 수 없습니다.
-
22-08-2019 - |
문제
다음 코드를 컴파일 할 때 :
void DoSomething(int Numbers[])
{
int SomeArray[] = Numbers;
}
vs2005 컴파일러는 오류 C2440에 불만을 제기합니다. '초기화': 'int []'에서 'int []로'int [] '에서 변환 할 수 없습니다.
나는 그것이 작동하지 않을 배열에 대한 포인터를 시전하려고한다는 것을 이해합니다. 그러나 C ++를 배우는 사람에게 오류를 어떻게 설명합니까?
해결책
당신이 돕고 자하는 사람에게 설명해야 할 세 가지가 있습니다.
배열은 C ++의 함수로 값으로 전달할 수 없습니다. 당신이하려는 일을하려면 배열 시작 주소를 전달해야합니다.
DoSomething()
, 분리 된 배열의 크기뿐만 아니라int
(잘,size_t
, 그러나 나는 그렇게 말하는 것을 귀찮게하지 않을 것입니다) 논쟁. 일부 배열 시작 주소를 얻을 수 있습니다.myArray
표현과 함께&(myArray[0])
. 이것은 원하는 일반적인 일이므로 C ++는 배열의 이름 만 사용할 수 있습니다.myArray
- 첫 번째 요소의 주소를 얻습니다. C ++는 배열 유형을 지정할 수 있습니다 (예 :int Numbers[]
) 함수에 대한 매개 변수로서, 그러나 비밀리에 매개 변수는 마치 포인터로 선언 된 것처럼 취급합니다 (int *Numbers
이 경우) - 할 수도 있습니다Numbers += 5
내부에DoSomething()
여섯 번째 위치에서 시작하는 배열을 가리 킵니다!다음과 같은 배열 변수를 선언 할 때
SomeArray
C ++에서는 명시 적 크기 또는 "이니셜리스트 목록"을 제공해야합니다., 이것은 쉼표로 구분 된 값의 값 목록입니다. 컴파일러가 초기화하려는 다른 배열을 기반으로 배열의 크기를 추론 할 수 없습니다.한 배열을 다른 배열로 복사하거나 C ++의 다른 배열에서 하나의 배열을 초기화 할 수 없습니다. 따라서 매개 변수라도
Numbers
실제로 배열 (크기 1000)이었고 포인터가 아니 었으며 크기를 지정했습니다.SomeArray
(다시 1000으로) 라인int SomeArray[1000] = Numbers;
불법입니다.
당신이하고 싶은 일을하기 위해 DoSomething()
, 먼저 스스로에게 물어보세요 :
- 값을 변경해야합니까?
Numbers
? - 그렇다면 발신자가 이러한 변경 사항을 보지 못하게하고 싶습니까?
두 질문에 대한 답이 "아니오"라면 실제로 사본을 만들 필요는 없습니다. Numbers
우선 - 그냥 그대로 사용하고 별도의 것을 잊어 버리십시오. SomeArray
정렬.
두 질문 모두에 대한 답이 "예"인 경우 사본을 만들어야합니다. Numbers
안에 SomeArray
대신 작업하십시오. 이 경우 실제로 만들어야합니다 SomeArray
C ++ vector<int>
이것은 다른 배열 대신 실제로 물건을 단순화합니다. (수동 동적 메모리 할당에 대한 벡터의 이점을 설명합니다. ~할 수 있다 다른 배열 또는 벡터에서 초기화되면 C 스타일과 달리 필요한 경우 요소 생성자를 호출합니다. memcpy()
.)
다른 팁
유형과 불완전한 유형이 있다고 가정하십시오.
struct A;
A라는 구조물의 불완전한 유형입니다.
struct A { };
A라는 구조물의 완전한 유형입니다. 첫 번째 크기는 아직 알려지지 않았으며 두 번째 크기는 알려져 있습니다.
위 구조물과 같은 불완전한 클래스 유형이 있습니다. 그러나 불완전한 배열 유형도 있습니다.
typedef int A[];
그것은 A라는 불완전한 배열 유형입니다. 크기는 아직 알려져 있지 않습니다. 컴파일러가 배열이 얼마나 큰지 알지 못하기 때문에 배열을 만들 수 없습니다. 하지만 당신은 할 수 있습니다 사용 배열을 만들기 위해 뿐 바로 초기화하면 :
A SomeArray = { 1, 2, 3 };
이제 컴파일러는 배열이 3 개의 요소가있는 int 배열임을 알고 있습니다. 포인터로 배열을 초기화하려고하면 컴파일러가 이전보다 더 영리하지 않으며 거부 할 배열의 크기를 제공하지 않기 때문에 거부합니다.
오류 메시지를보다 도움이 되려고 노력할 때 컴파일러는 실제로 혼란 스럽습니다. 비록 Numbers
매개 변수는 배열로 선언되며 C/C ++는 실제로 배열을 전달할 수 없습니다 - Numbers
매개 변수는 실제로 포인터입니다.
따라서 오류는 실제로 말해야합니다 "cannot convert from 'int *' to 'int []'"
하지만 혼란이있을 것입니다 - "이봐, int*
표현에 관여한다 ", 누군가는 말할 수있다.
이러한 이유로 배열 매개 변수를 피하는 것이 실제로 좋습니다. 그리고 C/C ++를 배우는 사람에 대한 설명은 배열 매개 변수가 허구라는 사실에 대해 교육해야합니다. 그들은 실제로 포인터입니다.
내가 무언가를 설명하려고 할 때, 나는 항상 가장 낮은 수준으로 내려 가서 거기에서 쌓이려 고 노력합니다. 그것이 내가 배우고 싶어하는 방식이며, 그들이 알고있는 기본 사항을 시작하고 거기에서 쌓이면 사람들이 더 편한다는 것을 알게됩니다.
이 경우 아마도 다음과 같은 것으로 시작합니다.
할당 작업을 작성했기 때문에 컴파일러가 과제를 수행하려고합니다. C ++에서는 배열에 직접 할당 할 수 없습니다 (모든 종류의 할당 연산자가 없기 때문에) (모든 종류의 이니셜 라이저 및 인덱싱 만 배열에 대한 지원). C ++는 유형에 대해 과부하 된 연산자를 지원하기 때문에 컴파일러는 "할당 된"유형을 인수로 가져 오는 "할당 된"유형의 과부하 할당 연산자를 찾습니다. int []를 인수로 가져 오는 int []에 대한 오버로드 된 연산자도 없기 때문에 라인의 컴파일러 오류가 발생하며 오류가 컴파일러가 라인을 처리 할 수없는 이유를 알려줍니다.
그렇습니다. 아마도 크기, 불완전한 유형 등에 대한 지식에 대해 말하는 것보다 과도한 일일 것입니다. 나는 그것이 완전하지 않다는 것을 알고 있습니다 (예 : 초기 할인 할당 대 일반 할당 등에 대한 논의 없음). 그러나 저의 목표는 일반적으로 사람들이 다음 답변을 파악할 수있는 곳으로 데려가는 것입니다.이 때문에 대개 답변에 도달하기위한 사고 과정을 제시하고자합니다.
아마도 당신의 대답은 "컴파일러가 배열이 얼마나 큰지 모르기 때문에"일 수 있습니다.
명백한 배열 크기 (명확성을위한 typedef)가있는 경우 예제가 작동 할 수 있으며 가변 크기 할당을 도입하면서 포인터를 설명 할 수 있습니다.