2014-05-17 7 views
0

다음 코드를 디버깅하려고 시도하고 "액세스 위반"오류가 발생합니다. 첫 번째 루프가 모든 요소에 액세스 할 수있는 동안 요소의 두 번째 행에 액세스 할 때 왜 두 번째 루프가 실패하는지 이해할 수 없습니다.2D 배열 액세스 위반

나는 *, &[]을 엉망으로 만들고 있지만 알아낼 수는 없습니다.

감사합니다.

#include <iostream> 

void a(const int* data, unsigned int nElements, unsigned int nColumns) { 

    for (unsigned int i = 0; i < nElements; ++i) 
     std::cout << data[i]; 

    for (unsigned int i = 0; i < nElements/nColumns; ++i) 
     for (unsigned int j = 0; j < nColumns; ++j) 
      std::cout << (&data)[i][j]; 
} 

int main() { 
    int arr[2][5] = { 
     { 0, 1, 2, 3, 4 }, 
     { 5, 6, 7, 8, 9 } 
    }; 

    a(*arr, 2 * 5, 5); 

    return 0; 
} 
+0

조금 더 노력하려고 설명해 주시겠습니까? 다소 불분명합니다. – Ben

+0

실제 문제는 여기에 있습니다 : (& data) [i]. 데이터는 인수의 단일 요소이기 때문에 & data는 단일 요소에 대한 포인터입니다. 이것은 i> 0이 문제라는 것을 의미합니다. 다차원 배열은 실제로는 메모리 블록이며 다차원 배열에서 [i] [j]를 수행하면 컴파일러에서 포인터 배열에 대해 [i] [j]와 다르게 처리합니다. 다차원 배열의 [i] [j]는 [i * numcolumns + j]와 같습니다. – thang

답변

0

당신은 모든 종류의 정보를 잃어버린 것 배열에있는 크기입니다. 매개 변수 목록에서 크기를 지정 첨자가 작동합니다

void a(int const (&data)[2][5]) { 
    for (auto const& row : data) 
    for (auto i : row) 
     ::std::cout << i << " "; 
    ::std::cout << ::std::endl; 
} 

그런 다음도 미쳐과에 프로토 타입을 변경할 수 있습니다

template <size_t R, size_t C> 
void a(int const (&data)[R][C]) { 

는 그래서 모든 2D 배열 작동합니다.

+0

'a (arr, 2 * 5, 5);'인수를 전달할 때 별표를 제거하고 예제에서와 같이 매개 변수의 크기를 지정하고 데이터에 액세스 할 때 앰퍼샌드를 제거하면 두 개의 첨자 연산자. 첫 번째 루프가 동일한 메모리에 액세스 할 수 있으므로 범위를 벗어난 것으로 생각하지 않았습니다. 그리고 그것은 당신이 첫 번째 문장의 첫 부분에서 대답 한 질문이었습니다. 그러나, 나는 아직도 당신이 "모든 유형의 정보를 잃어 버렸다"는 것을 이해하지 못합니다. 좀 더 자세히 설명해 주시겠습니까? 아니면 그것에 대해 더 많이 읽을 수있는 출처를 공유 할 수 있습니까? 고맙습니다. – user2570380

+0

@ user2570380 :'a [1] [2]'라고 할 때, a [1]이 올바른 주소 (배열 1의 원소 0)로 해석되기 위해서는 타입 시스템이 필요합니다. . 이는 주소가 두 번째 차원의 * 크기 *에 달려 있기 때문입니다. 만약 당신이 2x5'int' 배열을 가지고 있다면, 첫 번째 첨자의 모든 증가분은 5 개의 int 값을 "점프"해야합니다. 런타임 유형과 일치하는 정적 유형으로 만 수행 할 수 있습니다. 만약 당신이 가지고있는 것이'int *'라면 컴파일러 나 cpu는'a [1] [2]'로 무엇을 해야하는지 알고 있어야합니까? – bitmask

1

*arrarr[0] 같다 *(arr + 0) 같다.

a(*arr, 5, 5); 
2

(&data)[i] 명확 가짜입니다 : arr[0]은뿐만 아니라, 10 호출이 같은 기능을 5 nElements 있습니다. data은 배열이 아닌 변수입니다. (&data)[0]을 작성하고 하나의 요소가있는 배열과 같은 변수를 처리하는 것은 합법적입니다. 그러나 i > 0 인 경우 data이 저장된 후 메모리에 액세스하려고 시도합니다. 이는 소유 한 메모리가 아닙니다. (data 포인터를 가리키는 것과 섞지 마십시오.)

당신이 찾고있는 구문은 다음과 같습니다

std::cout << data[i * nColumns + j]; 

* 물론 곱셈이 아닌 참조 연산자이다. 이 함수를 호출 할 때 배열을 10 요소 1 차원 배열처럼 처리하여 배열을 "평평하게"하므로 산술을 사용하여 필요한 인덱스를 완성해야합니다.

마지막으로 함수 호출에서 *arr(int *)&arr 또는 (int *)arr이어야합니다. 실제로 작성한 것은 이며 5 요소 배열입니다. 그것은 당신의 기능에서 그것으로부터 5 개 이상의 요소를 시도하고 읽는 제한된 접근입니다. 실제로, 컴파일러는 효율성을 이유로 범위를 벗어난 액세스를 탐지하려고 시도하지 않으며 작동하는 것으로 보입니다.

1

변경에 루프에 대한 이중의 라인 : 당신이 당신의 a 기능에 한 번 당신이 말을하지 않는 첨자 연산자 일을 기대하지 수

std::cout << data[i * nColumns + j];