변수 크기 유형은 모든 기능 외부에 선언되었습니다
-
07-07-2019 - |
문제
2 차원 배열을 선언 할 때
int random[height][width];
그런 다음 함수에서 사용합니다
void populate(int random[height][width], int x, int y)
모든 함수 외부에 선언 된 오류 변수 크기 유형을 제공합니다. 나는 내가 뭔가 잘못하고 있다는 것을 알고 있습니다. 나는 단지 기억이 나쁘다 ...
해결책
나는 지금 강화하고 다차원 배열이 C 또는 C ++의 뇌 노력의 가치가 없다고 말할 것입니다. 단일 차원 배열 (또는 더 나은 표준 컨테이너)을 사용하고 인덱싱 기능을 작성하는 것이 훨씬 좋습니다.
inline int index (int x, int y)
{
return x + y * width;
}
이제 당신의 문제에 대해. C ++는 C99 가변 길이 배열을 지원하지 않습니다. 컴파일러는 컴파일 시간에 배열의 크기를 알아야합니다. 예를 들어 다음은 작동하지 않습니다.
int dim = 4;
int ar[dim];
만약에 dim
~이었다 const
, 컴파일러가 정확히 얼마나 넓은지를 알 수 있기 때문에 작동합니다. ar
(가치 때문에 dim
변하지 않을 것입니다). 이것은 아마도 당신이 직면 한 문제 일 것입니다.
컴파일 타임에 크기를 변경하려면 템플릿 참조를 작성하는 것과 같이 더 어려운 일을해야합니다. C/C ++에 배치 된 방식으로 인해 다차원 배열에 대한 포인터를 사용할 수 없습니다. 템플릿 예제는 다음과 같은 수차처럼 보일 수 있습니다.
template <int Width, int Height>
void populate(int (&(&random)[Width])[Height], int x, int y);
이것은 추악합니다.
런타임에는 사용해야합니다 new
데이터를 할당하거나 컨테이너 유형을 사용합니다.
다른 팁
컴파일 타임에서 치수가 알려지지 않기 때문에 기능 외부에서 비 스턴트 치수 (너비, 높이)로 배열을 정의 할 수 없습니다. 상수를 사용하거나 동적으로 (힙 또는 스택 프레임에) 동적으로 할당해야합니다.
배열이 매개 변수로 직접 전달되면 (전달 값) 배열의 첫 번째 요소에 대한 포인터로 감소합니다. 서명에서 배열의 크기를 명확하게 읽을 수 있더라도 해당 크기는 컴파일러에 의해 무시됩니다. 그 행동은 C와 호환됩니다.
C ++를 사용하면 더 이상 배열을 참조 할 수 있으며 더 이상 문제가되지 않습니다.
int extract_value( int (&a)[10][10], int row, int col ) {
return a[row][col];
}
int main() {
int a[10][10] = {};
a[5][5] = 1;
std::cout << extract_value( a, 5, 5 ) << std::endl;
int b[5][5];
// extract_value( b, 2, 2 ); // error: the function takes an array of 10x10
}
함수 매개 변수는 정확히 일치해야합니다. 즉, 10x10 요소의 배열 만 필요합니다. 배열 크기의 함수를 템플릿으로하여 해당 제한을 제거 할 수 있습니다. 일단 당신이 그것에 있으면 유형도 있습니다.
template <typename T, int Rows, int Cols>
T extract_value( T (&a)[Rows][Cols], int row, int col ) {
return a[row][col];
}
int main() {
int a[5][7] = {};
extract_value( a, 3, 4 );
int b[8][2] = {};
extract_value( b, 7, 1 ); // correct, the compiler matches sizes
double c[4][4] = {};
extract_value( c, 2, 2 ); // different types are allowed
}
이 솔루션은 크기가 시간 상수를 컴파일해야하며 배열을 쌓아야한다는 점에서 여전히 번거 롭습니다. 이에 대한 해결책은 버퍼 (선형)에서 동적 메모리를 취하고 n- 코디네이트 시스템에서 1 차원 배열로 변환하여 이전에 제안 된 바와 같이 값을 얻는 일부 클래스를 정의하는 것입니다. 이것에서 그것을하는 방법에 대한 힌트를 얻을 수 있습니다. 자주하는 질문 2D 매트릭스 구현을 제공하는 연산자 과부하에 대해. 구현 된 후에는 함수/메소드의 매개 변수로 사용할 수 있습니다.
내 권장 사항은이 마지막 경로를 따르는 것입니다. N- 차원 배열을 1D 벡터로 전환하는 클래스로 캡슐화합니다 (C ++ FAQ 라이트는 원시 포인터를 사용하고 STL 컨테이너를 선호합니다).
나는 예를 들어 다음과 같이 설명 할 것이다.
// 글로벌
const int ARRAY_SIZE = 16
struct ArrayType_t arrayType[ARRAY_SIZE];
Array_Size가 일정한 int로 선언 되더라도 컴파일 시간에 값이 초기화되지 않으므로 컴파일러는 배열의 크기를 알지 못하고 그러한 오류를 제공합니다. 그러나 해시 정의로 만들 경우#define ARRAY_SIZE 16
struct ArrayType_t arrayType[ARRAY_SIZE]
===> array_size는 컴파일 시간에 정의되며 컴파일러는 컴파일 시간에 배열의 크기를 알 수 있기 때문에 작동합니다.
다음과 같은 것을 사용할 수 있습니다.
void populate(int height, int width, int **random)
{
//here you can work from random[0][0] to random[height][width]
}
그런 다음 다음과 같이 사용할 수 있습니다.
int main()
{
int height=10;
int width=20;
int **myarray = new int*[height];
for( int i=0; i< height; i++ ) myarray[i] = new int[width];
populate( height, width, myarray);
}
그러나 물론, 당신은 버퍼 오버플로를 조심해야 할 것입니다