2017-04-10 1 views
2

이전에 물어 보면 미리 사과드립니다. 찾지 못했습니다.C Matrix Dimension from Declaration

실용적인 것은 거의없는 이상한 버그 일뿐입니다. I 다른 기능이 매트릭스를 사용하여 크기를 호출 할 때, I는 크기의 행렬을 선언

#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 

void print_matrix(int a[4][3], int i, int j) 
{ 
    printf("a[%d][%d] = %d\n", i, j, a[i][j]); 
    return; 
} 

int main(void) 
{ 
    int i, j; 
    int array[3][5]; 
    for (i = 0; i < 3; i++) 
    { 
     for(j = 0; j < 5; j++) 
     { 
      scanf("%d",&(array[i][j])); 
     } 
    } 
    printf("array[2][1] = %d\n", array[2][1]); 
    print_matrix(array, 2, 1); 
    printf("array[0][4] = %d\n", array[0][4]); 
    print_matrix(array, 0, 4); 
    return 0; 
} 

[3] [5]하지만, [4] [3], 그 이상 결과를 반환 여기서 코드는 . 누군가이 시나리오에서 메모리에 액세스하는 방법을 설명 할 수 있습니까?

+0

컴파일러에서 경고해야합니다. 모든 경고가 사용 가능하도록 컴파일하십시오. –

+0

단순히 void print_matrix (int x, int y, int a [x] [y])'로 함수를 변경하십시오. C는 크기가 0 인 배열을 허용하지 않습니다. – Lundin

답변

2

코드에 정의되지 않은 동작이 있으므로 아무 일도 발생할 수 없습니다. 함수의 첫 번째 인수는 3 정수의 배열에 대한 포인터 인 int (*a)[3]이 될 것으로 예상됩니다. 함수 매개 변수로서의 배열은 항상 포인터로 감쇠되며,이 경우에는 배열에 대한 포인터입니다. 그러나 array을 전달하면 int(*)[5]으로 5 개의 정수 배열에 대한 포인터가됩니다. C11 표준의 다음 하위 섹션에 따르면

는 두 포인터 타입이 호환 될 수 있도록

[§6.7.6.1 ¶2]

를 들어, 모두 동일하게 규정되어야하며, 모두 호환 유형에 대한 포인터한다. 두 개의 배열 형 호환되기 위해서는

[§6.7.6.2 ¶6]

모두 호환 요소 유형을 가진다 모두 크기 지시자가 존재하고, 상수 식 정수 경우, 다음 두 크기 지정자 동일 ​​가진다 상수 값. 두 배열 유형이 호환 가능해야하는 컨텍스트에서 사용되는 경우 두 크기 지정자가 부동 소수점으로 평가되는 경우 정의되지 않은 동작입니다.

포인터 유형이 호환되지 않기 때문에 컴파일러는 제한없이 원하는 코드를 내보낼 수 있습니다. 코드는 정의되지 않은 행동의 의미 인 의미를 갖출 필요조차 없습니다.

하지만 (확실히 다른 컴파일러) GCC는 코드에 대해 다음과 같은 경고를 방출 할 수있다 :

warning: passing argument 1 of 'print_matrix' from incompatible pointer type [-Wincompatible-pointer-types] 

그래서 항상 활성화 경고와 함께 컴파일, 그들을주의!


아마 가장 많이 발생하는 일로, 다차원 배열에 대해 배열 액세스가 이루어지는 방식을 고려해야합니다. 당신이 a[i][j]을 쓸 때 그것은으로 해석 될 수 있도록 크기 (3) 배열 정의의 일부입니다

*(a + i * 3 + j) 

그러나이 array에 대한 올바른 연산 아니라, 올바른 액세스는

*(array + i * 5 + j) 
에 해당이

따라서 본질적으로 array에서 a까지 읽으면 잘못된 셀에 액세스하게됩니다.