programing

2차원 배열 포인터 만들기

nicescript 2022. 7. 14. 21:45
반응형

2차원 배열 포인터 만들기

정적 2차원 배열에 대한 포인터가 필요해이거 어떻게 하는 거야?

static uint8_t l_matrix[10][20];

void test(){
   uint8_t **matrix_ptr = l_matrix; //wrong idea 
}

다음과 같은 모든 종류의 오류가 발생합니다.

  • 경고: 호환되지 않는 포인터 유형으로부터의 할당
  • 첨자 값이 배열도 아니고 포인터도 아닙니다.
  • 오류: Flexible Array 멤버의 잘못된 사용

여기서 배열의 첫 번째 요소에 대한 포인터를 만듭니다.

uint8_t (*matrix_ptr)[20] = l_matrix;

typedef를 사용하면 더 깔끔해 보입니다.

typedef uint8_t array_of_20_uint8_t[20];
array_of_20_uint8_t *matrix_ptr = l_matrix;

그러면 인생을 다시 즐길 수 있어:)

matrix_ptr[0][1] = ...;

C의 포인터/배열 세계를 주의해 주세요.주변은 매우 혼란스럽습니다.


편집

코멘트 필드가 너무 짧기 때문에 여기서 다른 답변을 검토 중입니다.여러 가지 대안이 제시되었지만, 그들이 어떻게 행동하는지는 보여주지 않았다.그들은 이렇게 한다.

uint8_t (*matrix_ptr)[][20] = l_matrix;

"Address-of" 를 추가한 경우&

uint8_t (*matrix_ptr)[][20] = &l_matrix;

그런 다음 20 uint8_t 유형 배열 요소의 불완전한 배열 유형에 대한 포인터를 만듭니다.포인터는 어레이 어레이에 대한 것이므로 다음 명령을 사용하여 액세스해야 합니다.

(*matrix_ptr)[0][1] = ...;

또한 불완전한 배열에 대한 포인터이므로 숏컷으로는 할 수 없습니다.

matrix_ptr[0][0][1] = ...;

인덱싱은 요소 유형의 크기를 알아야 하기 때문에(인덱싱은 포인터에 정수를 추가해야 하므로 불완전한 유형에서는 작동하지 않습니다. 이음음, 음음음음음 에서만 기능한다는 점에 해 주세요.C, 냐냐T[] ★★★★★★★★★★★★★★★★★」T[N]는 호환성이 있는 타입입니다.C++ 에는 호환성이 있는 타입의 개념이 없기 때문에, 그 코드는 거부됩니다.T[] ★★★★★★★★★★★★★★★★★」T[10]른른른타타타다다


다음 대체 방법은 전혀 작동하지 않습니다. 왜냐하면 어레이를 1차원 어레이로 볼 때 어레이의 요소 유형은 uint8_tuint8_t[20]

uint8_t *matrix_ptr = l_matrix; // fail

다음은 좋은 대안입니다.

uint8_t (*matrix_ptr)[10][20] = &l_matrix;

접속처:

(*matrix_ptr)[0][1] = ...;
matrix_ptr[0][0][1] = ...; // also possible now

외부 치수의 크기를 유지할 수 있다는 장점이 있습니다.사이즈를 적용해서

sizeof (*matrix_ptr) == sizeof(uint8_t) * 10 * 20

배열의 항목이 연속적으로 저장된다는 사실을 활용하는 다른 답변이 있습니다.

uint8_t *matrix_ptr = l_matrix[0];

이제 정식으로 2차원 배열의 첫 번째 요소에만 액세스할 수 있습니다.즉, 다음 조건의 보류

matrix_ptr[0] = ...; // valid
matrix_ptr[19] = ...; // valid

matrix_ptr[20] = ...; // undefined behavior
matrix_ptr[10*20-1] = ...; // undefined behavior

이 최고가 될 입니다.10*20-1그러나 에일리어스 분석이나 다른 적극적인 최적화를 실시하면 일부 컴파일러가 그 코드를 파괴할 가능성이 있다고 추측할 수 있습니다.가 발생한 그 코드에서 한 적은 C 에도 이 유형을 할 수 또한 C FAQ에도 해당 기술이 포함되어 있습니다(UB'ness에 대한 경고 포함). 어레이 유형을 변경할 수 없는 경우에는 이 옵션이 마지막 옵션입니다.

를 완전히 이해하려면 다음 개념을 이해해야 합니다.

배열은 포인터가 아닙니다!

우선 어레이는 포인터가 아닙니다(이미 충분히 설명되었습니다.대신 대부분의 경우 포인터에 할당할 수 있는 첫 번째 요소에 대한 주소로 '감쇠'합니다.

int a[] = {1, 2, 3};

int *p = a; // p now points to a[0]

이렇게 하면 어레이의 콘텐츠를 모두 복사하지 않고 액세스할 수 있습니다.이것은 어레이 타입의 동작일 뿐, 같은 것을 의미하는 것은 아닙니다.



다차원 어레이

다차원 배열은 컴파일러/머신이 이해하고 조작할 수 있는 방법으로 메모리를 '파티션'하는 방법입니다.

를 들면, 「 」입니다.int a[4][3][5]= 4*3*5(60)입니다.

「 」를 사용하는 것에 int a[4][3][5] 플레인 vs 레 vsint b[60]이제 '파티션'이 되어(필요에 따라 '청크'와 작업하기 쉬워짐) 프로그램이 바운드 체크를 수행할 수 있게 되었습니다.

ㅇㅇㅇㅇ.int a[4][3][5]다음과 같이 저장됩니다.int b[60]in memory - 유일한 차이점은 프로그램이 특정 크기의 개별 엔티티인 것처럼 관리한다는 것입니다(구체적으로는 3개의 그룹으로 구성된 4개의 그룹 5개).

: 둘 다.int a[4][3][5] ★★★★★★★★★★★★★★★★★」int b[60], /어플리케이션/어플리케이션/어플리케이션/어플리케이션/어플리케이션/어플리케이션/어플리케이션/어플리케이션/어플리케이션/어플리케이션/어플리케이션/어플리케이션/어플리케이션/어플리케이션/어플리케이션/어플리케이션/어플리케이션/의 처리방법뿐입니다.

{
  {1, 2, 3, 4, 5}
  {6, 7, 8, 9, 10}
  {11, 12, 13, 14, 15}
}
{
  {16, 17, 18, 19, 20}
  {21, 22, 23, 24, 25}
  {26, 27, 28, 29, 30}
}
{
  {31, 32, 33, 34, 35}
  {36, 37, 38, 39, 40}
  {41, 42, 43, 44, 45}
}
{
  {46, 47, 48, 49, 50}
  {51, 52, 53, 54, 55}
  {56, 57, 58, 59, 60}
}

이를 통해 각 "파티션"은 프로그램이 추적하는 어레이에 불과함을 명확하게 알 수 있습니다.



구문

어레이는 포인터와 구문적으로 다릅니다.이는 컴파일러/머신이 이들을 다르게 취급한다는 것을 의미합니다.이것은 간단한 것처럼 보일 수 있지만, 이것 좀 보세요.

int a[3][3];

printf("%p %p", a, a[0]);

위의 예에서는 다음과 같이 같은 메모리주소를 2회 인쇄합니다.

0x7eb5a3b4 0x7eb5a3b4

단, 포인터에 직접 할당할 수 있는 것은 1개뿐입니다.

int *p1 = a[0]; // RIGHT !

int *p2 = a; // WRONG !

할 수 없는 이유 a 포인터에 할당되어 있지만 a[0] 할 수 있나요?

이는 단순히 다차원 배열의 결과이며, 그 이유를 설명하겠습니다.

」의 a'할 수 또 다른 '기대해야 할을 알 수 있습니다우리는 여전히 기대할 수 있는 또 다른 '기대해야 할'이 있음을 알 수 있다. 」의 a[0]「그러나, 이미 톱 디멘션에 들어가 있기 때문에, 이 프로그램에 관한 한, 일반적인 어레이에 지나지 않습니다.

다음과 같이 질문할 수 있습니다.

어레이의 포인터 작성에 있어서 어레이가 다차원적인 것이 중요한 이유는 무엇입니까?

이렇게 생각하는 것이 가장 좋습니다.

다차원 배열의 '감쇠'는 단순한 주소가 아니라 파티션 데이터가 있는 주소(기본 데이터가 다른 배열로 구성되어 있음을 인식하는 AKA)입니다. 이 주소는 첫 번째 차원을 넘어 배열에 의해 설정된 경계로 구성됩니다.

이 '파티션' 논리는 지정하지 않는 한 포인터 내에 존재할 수 없습니다.

int a[4][5][95][8];

int (*p)[5][95][8];

p = a; // p = *a[0] // p = a+0

그렇지 않으면 배열의 정렬 속성의 의미가 손실됩니다.

, 「 」, 「 」의 주위에 하는 것에 주의해 주세요.*pint (*p)[5][95][8] 이 이 것이 이 로 포인터를 만드는 것을 int *p[5][95][8]



결론

리뷰:

  • 사용된 컨텍스트에 다른 목적이 없는 경우 어레이는 주소로 감소합니다.
  • 다차원 어레이는 어레이의 어레이일 뿐입니다.따라서, 「소형」주소는 「하위 치수가 있다」라고 하는 부담을 수반합니다.
  • 차원 데이터는 사용자가 지정하지 않으면 포인터에 존재할 수 없습니다.

요약하면, 다차원 어레이는, 그 내용을 이해할 수 있는 주소가 됩니다.

멀티디멘셔널 어레이를 가리키는 포인터 초기화 기본 구문은 다음과 같습니다.

type (*pointer)[1st dimension size][2nd dimension size][..] = &array_name

호출의 기본 구문은 다음과 같습니다.

(*pointer_name)[1st index][2nd index][...]

다음은 예를 제시하겠습니다.

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

int main() {
   // The multidimentional array...
   char balance[5][100] = {
       "Subham",
       "Messi"
   };

   char (*p)[5][100] = &balance; // Pointer initialization...

   printf("%s\n",(*p)[0]); // Calling...
   printf("%s\n",(*p)[1]); // Calling...

  return 0;
}

출력:

Subham
Messi

성공했어...

음의 인덱스를 사용하려는 경우 오프셋을 추가할 수도 있습니다.

uint8_t l_matrix[10][20];
uint8_t (*matrix_ptr)[20] = l_matrix+5;
matrix_ptr[-4][1]=7;

컴파일러에 에러나 경고가 표시되는 경우는, 다음을 사용할 수 있습니다.

uint8_t (*matrix_ptr)[20] = (uint8_t (*)[20]) l_matrix;

어레이를 선형으로 선언하고 (row, col) to array 인덱스를 직접 계산함으로써 컴파일러를 만지작거리지 않아도 됩니다.

static uint8_t l_matrix[200];

void test(int row, int col, uint8_t val)

{

   uint8_t* matrix_ptr = l_matrix;
   matrix_ptr [col+y*row] = val; // to assign a value

}

어쨌든 컴파일러는 이렇게 했을 겁니다.

안녕하세요.

선언문

static uint8_t l_matrix[10][20];

는 20개의 unit8_t 로케이션, 즉 200개의 uint8_t 사이즈 로케이션의 10행분의 저장 공간을 확보하고 있으며 각 요소는 20x행 + 열을 계산하여 찾을 수 있습니다.

그렇지도 않다

uint8_t (*matrix_ptr)[20] = l_matrix;

필요한 정보를 제공하고 배열의 첫 번째 행의 열 0 요소를 가리킬 수 있습니까?

편집: 좀 더 자세히 생각해 보면 어레이 이름은 정의상 포인터 아닌가요?즉, 배열의 이름은 첫 번째 요소의 위치와 동의어입니다.즉, l_matrix[0][0]?

편집 2: 다른 사람들이 언급했듯이, 더 이상의 논의를 하기에는 코멘트 공간이 너무 좁습니다.어쨌든:

typedef uint8_t array_of_20_uint8_t[20];
array_of_20_uint8_t *matrix_ptr = l_matrix;

에서는 문제의 어레이에 대한 스토리지 할당을 제공하지 않습니다.

위에서 언급한 바와 같이, 그리고 표준에 의해 정의된 바와 같이, 진술서는 다음과 같다.

static uint8_t l_matrix[10][20];

는 타입 uint8_t의 200개의 연속된 위치를 확보했습니다.

형식의 문구를 사용한 l_matrix 참조:

(*l_matrix + (20 * rowno) + colno)

rowno 행에 있는 colno'th 요소의 내용이 표시됩니다.

모든 포인터 조작은 가리키는 오브젝트의 크기를 자동으로 고려합니다.- K&R Section 5.4, 페이지 103

이는 또한 패딩 또는 바이트 정렬 시프트가 수중에 있는 오브젝트 저장에 관여하는 경우에도 마찬가지입니다.컴파일러는 이러한 기능을 자동으로 조정합니다.C ANSI 표준의 정의에 의해.

HTH

건배.

int *ptr= l_matrix[0];

다음과 같이 접속할 수 있습니다.

*p
*(p+1)
*(p+2)

2차원 배열도 모두 1-d로 저장됩니다.

C99(clang 및 gcc에서 지원됨)에는 다차원 배열을 함수에 참조로 전달하기 위한 불분명한 구문이 있습니다.

int l_matrix[10][20];

void test(int matrix_ptr[static 10][20]) {
}

int main(void) {
    test(l_matrix);
}

일반 포인터와 달리 이는 어레이 크기에 대한 힌트를 주기 때문에 이론적으로 컴파일러가 너무 작은 어레이를 통과하는 것에 대해 경고하고 명백한 범위 밖의 액세스를 발견할 수 있습니다.

슬프게도, 그것은 고쳐지지 않는다.sizeof()컴파일러는 아직 그 정보를 사용하지 않는 것 같아서 궁금하네요.

다음과 같이 할 수 있습니다.

uint8_t (*matrix_ptr)[10][20] = &l_matrix;

첫 번째 요소에 대한 포인터가 필요하기 때문에

static uint8_t l_matrix[10][20];

void test(){
   uint8_t *matrix_ptr = l_matrix[0]; //wrong idea 
}

언급URL : https://stackoverflow.com/questions/1052818/create-a-pointer-to-two-dimensional-array

반응형