왜 x [0]! = x [0] [0]! = x [0] [0] [0]입니까? 이것은 *x포인터 인 5 개 요소의 배열에

나는 약간의 C ++을 공부하고 있으며 포인터와 싸우고 있습니다. 다음과 같이 선언하면 3 단계의 포인터를 가질 수 있음을 이해합니다.

int *(*x)[5];

그래서 이것은 *x포인터 인 5 개 요소의 배열에 대한 포인터 int입니다. 또한 내가 알고 x[0] = *(x+0);, x[1] = *(x+1)등등 및 ….

위의 선언에서 왜 그렇 x[0] != x[0][0] != x[0][0][0]습니까?



답변

x에 대한 5 개의 포인터 배열에 대한 포인터 int입니다.
x[0]에 대한 5 개의 포인터 배열 입니다 int.
x[0][0]에 대한 포인터 int입니다.
x[0][0][0]입니다 int.

                       x[0]
   Pointer to array  +------+                                 x[0][0][0]         
x -----------------> |      |         Pointer to int           +-------+
               0x500 | 0x100| x[0][0]---------------->   0x100 |  10   |
x is a pointer to    |      |                                  +-------+
an array of 5        +------+                        
pointers to int      |      |         Pointer to int                             
               0x504 | 0x222| x[0][1]---------------->   0x222                    
                     |      |                                             
                     +------+                                             
                     |      |         Pointer to int                              
               0x508 | 0x001| x[0][2]---------------->   0x001                    
                     |      |                                             
                     +------+                                             
                     |      |         Pointer to int                              
               0x50C | 0x123| x[0][3]---------------->   0x123                    
                     |      |                                             
                     +------+                                             
                     |      |         Pointer to int                              
               0x510 | 0x000| x[0][4]---------------->   0x000                    
                     |      |                                             
                     +------+                                             

당신은 그것을 볼 수 있습니다

  • x[0]는 배열이며 표현식에서 사용될 때 첫 번째 요소에 대한 포인터로 변환됩니다 (일부 예외 제외). 따라서 x[0]첫 번째 요소의 주소 x[0][0]0x500입니다.
  • x[0][0]의 주소가 포함되어 int있는이 0x100.
  • x[0][0][0]int값을 포함합니다 10.

따라서 x[0]동일하다 &x[0][0]그러므로 및, &x[0][0] != x[0][0].
따라서 x[0] != x[0][0] != x[0][0][0].


답변

x[0] != x[0][0] != x[0][0][0]

자신의 게시물에 따르면

*(x+0) != *(*(x+0)+0) != *(*(*(x+0)+0)+0)`  

이것은 단순화

*x != **x != ***x

왜 평등해야합니까?
첫 번째는 포인터의 주소입니다.
두 번째는 다른 포인터의 주소입니다.
그리고 세 번째는 int가치입니다.


답변

다음은 포인터의 메모리 레이아웃입니다.

   +------------------+
x: | address of array |
   +------------------+
            |
            V
            +-----------+-----------+-----------+-----------+-----------+
            | pointer 0 | pointer 1 | pointer 2 | pointer 3 | pointer 4 |
            +-----------+-----------+-----------+-----------+-----------+
                  |
                  V
                  +--------------+
                  | some integer |
                  +--------------+

x[0]“어드레스 주소”,
x[0][0]“포인터 0”,
x[0][0][0]“일부 정수”를 나타냅니다.

나는 지금 분명해야한다고 생각한다. 왜 그들은 모두 다르다.


위의 내용은 기본적인 이해를 위해 충분히 가깝기 때문에 내가 쓴 방식으로 썼습니다. 그러나 헥스가 올바르게 지적했듯이 첫 번째 줄은 100 % 정확하지 않습니다. 자세한 내용은 다음과 같습니다.

C 언어의 정의에서 값 x[0]은 정수 포인터의 전체 배열입니다. 그러나 배열은 C에서 실제로 할 수없는 일입니다. 항상 주소 전체 또는 요소를 조작하고 전체 배열을 전체적으로 사용하지 마십시오.

  1. 운영자 x[0]에게 전달할 수 있습니다 sizeof. 그러나 그것은 실제로 값을 사용하는 것이 아니며 결과는 유형에만 달려 있습니다.

  2. 주소를 가져 와서 xtype의 “address of array” 값을 얻을 수 있습니다 int*(*)[5]. 다시 말해:&x[0] <=> &*(x + 0) <=> (x + 0) <=> x

  3. 에서는 모든 다른 콘텍스트 의 값은 x[0]상기 어레이의 첫번째 엘리먼트에 대한 포인터로 붕괴된다. 즉, “address of array”값과 유형이있는 포인터입니다 int**. 효과는 x유형의 포인터로 캐스팅 한 것과 같습니다 int**.

경우 3의 배열 포인터 붕괴로 인해, x[0]궁극적으로 모든 사용은 포인터 배열의 시작을 가리키는 포인터를 생성합니다. 이 호출 printf("%p", x[0])은 “어드레스 주소”라고 표시된 메모리 셀의 내용을 인쇄합니다.


답변

  • x[0]가장 바깥 쪽 포인터 ( int에 대한 포인터의 크기 5의 배열에 대한 포인터) 를 역 참조하고 포인터 의 크기 5의 배열을 만듭니다 int.
  • x[0][0]최 포인터 역 참조 포인터로 결과 인덱스 어레이 int;
  • x[0][0][0] 모든 것을 역 참조하여 구체적인 가치를 창출합니다.

그건 그렇고, 이러한 종류의 선언이 의미하는 것에 혼란 스러우면 cdecl을 사용하십시오 .


답변

단계 식으로 단계를 고려하자 x[0], x[0][0]하고 x[0][0][0].

x다음과 같이 정의됩니다

int *(*x)[5];

expression x[0]은 유형의 배열입니다 int *[5]. expression x[0]은 expression 과 동일 하다는 점을 고려하십시오 *x. 즉, 배열에 대한 포인터를 참조하여 배열 자체를 얻습니다. 선언처럼 y와 같이 표시하자

int * y[5];

표현식은와 x[0][0]동일하며 y[0]유형이 int *있습니다. 우리가 선언을했다 z와 같이 표시하자

int *z;

expression x[0][0][0]y[0][0]expression z[0]과 동등하며 expression 과 동등하며 type을 갖습니다 int.

그래서 우리는

x[0] 유형이있다 int *[5]

x[0][0] 유형이있다 int *

x[0][0][0] 유형이있다 int

따라서 그것들은 다른 유형의 객체와 다른 크기의 객체입니다.

예를 들어 실행

std::cout << sizeof( x[0] ) << std::endl;
std::cout << sizeof( x[0][0] ) << std::endl;
std::cout << sizeof( x[0][0][0] ) << std::endl;


답변

가장 먼저 말해야 할 것은

x [0] = * (x + 0) = * x;

x [0] [0] = * (* (x + 0) +0) = ** x;

x [0] [0] [0] = * (* (* (x + 0) +0)) = *** x;

따라서 * x ≠ * * x ≠ * * * x

다음 그림에서 모든 것이 명확합니다.

  x[0][0][0]= 2000

  x[0][0]   = 1001

  x[0]      = 10

여기에 이미지 설명을 입력하십시오

x [0] [0] [0] = 10 인 경우의 예일뿐입니다.

그리고 어드레스 X [0] [0] [0] 이다 1,001

해당 주소는 x [0] [0] = 1001에 저장됩니다.

x [0] [0]의 주소 는 2000입니다

그 주소는 x [0] = 2000에 저장됩니다

따라서 x [0] [0] [0] x [0] [0] x [0]

.

편집

프로그램 1 :

{
int ***x;
x=(int***)malloc(sizeof(int***));
*x=(int**)malloc(sizeof(int**));
**x=(int*)malloc(sizeof(int*));
***x=10;
printf("%d   %d   %d   %d\n",x,*x,**x,***x);
printf("%d   %d   %d   %d   %d",x[0][0][0],x[0][0],x[0],x,&x);
}

산출

142041096 142041112 142041128 10
10 142041128 142041112 142041096 -1076392836

프로그램 2 :

{
int x[1][1][1]={10};
printf("%d   %d   %d   %d \n ",x[0][0][0],x[0][0],x[0],&x);
}

산출

10   -1074058436   -1074058436   -1074058436 


답변

실제 관점에서 배열을 볼 경우 다음과 같이 나타납니다.

x[0]상자로 가득한화물 컨테이너입니다.
x[0][0]화물 컨테이너 안에 신발 상자로 가득 찬 단일 상자입니다.
x[0][0][0]상자 안에,화물 컨테이너 안에있는 단일 신발 상자입니다.

화물 컨테이너의 유일한 상자에있는 유일한 신발 상자 였음에도 불구하고 여전히화물 컨테이너가 아닌 신발 상자입니다