2015-08-11 8 views
8

Jako początkujący programista mam do czynienia z kilkoma prostymi problemami związanymi ze wskaźnikami. W poniższym kodzie znalazłem wartości *a i a są takie same w systemie szesnastkowym. Ale nie mogę zrozumieć przyczyny.Wskaźnik w tablicy 2D

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

main(){ 
    int a[5][5]; 
    a[0][0] = 1; 

    printf("*a=%p a=%p \n", *a, a); 

    return 0; 
} 

Oto wynik:

*a=0x7ffddb8919f0 a=0x7ffddb8919f0 
+1

C lub C++? Różne rzeczy – yizzlez

+0

Tak się składa, ponieważ adres 'a' i wartość zawarta w' * a' są takie same. –

Odpowiedz

5

w C i C++ języki wartości typu array T [N] są niejawnie konwertowane do wartości wskaźnika typu T * w większości kontekstów (z nielicznymi wyjątkami). Wynikowy wskaźnik wskazuje na pierwszy element oryginalnej tablicy (indeks 0). Zjawisko to jest nieoficjalnie znane jako rozpad tablicowy .

printf Argument ten jest jednym z tych przypadków, kiedy następuje zanikanie tablic .

Tablica 2D typu int [5][5] to nic innego jak "tablica 1D z tablic 1D", tj. Jest to tablica 5 elementów, z których każdy sam jest tablicą 5int s.

Powyższa reguła rozpadu typu tablicowego w naturalny sposób dotyczy tej sytuacji.

Wyrażenie a, które pierwotnie ma typ tablicy int [5][5], rozpada się na wskaźnik typu int (*)[5]. Wskaźnik wskazuje na element a[0], który jest początkiem tablicy podrzędnej a[0] w pamięci. To jest pierwszy wskaźnik, który drukujesz.

Wyrażenie *a jest operatorem dereferencyjnym zastosowanym do sub-wypowiedzi a. Sub-expression a w tym kontekście zachowuje się dokładnie w taki sam sposób jak poprzednio: rozpada się na wskaźnik typu int (*)[5], który wskazuje na a[0]. W związku z tym sam wynik jest następujący: *a. Ale a[0] jest także tablicą. Jest to tablica typu int[5].Jest również zależny od rozpadu typu tablicowego. Rozpada się na wskaźnik typu int *, który wskazuje na pierwszy element a[0], tj. Na a[0][0]. To jest drugi wskaźnik, który drukujesz.

Powód, dla którego obie wartości wskaźników są takie same, jest taki sam, jak początek podzbioru a[0] odpowiada tej samej lokalizacji pamięci, co element a[0][0].

1

a można uznać za pointer to a pointer to an int (w rzeczywistości jest to array of array of int, ale na tyle blisko).

Tak więc a i wskazują na ten sam adres (co zdarza się być a[0][0]).

*a jest nadal wskaźnikiem, a a[0] jest tym samym adresem, co a[0][0].

+0

To zbyt mylące, aby było przydatne. – juanchopanza

+0

@juanchopanza Przepraszam? Czy możesz wyjaśnić, dlaczego? – Jashaszun

+0

Absolutnie niepoprawna odpowiedź. "a" nie może być uważane za "wskaźnik do wskaźnika". Tablica 2D w C i C++ nie jest w żaden sposób powiązana z "wskaźnikiem do wskaźnika" – AnT

9

tablicy i jej pierwszy element mają ten sam adres. :)

Na tej deklaracji

int a[5][5]; 

ekspresji a używane w wywołaniu printf jest niejawnie konwertowane na wskaźnik do jej pierwszego elementu. Wyrażenie *a daje pierwszy element tablicy, który z kolei jest jednowymiarową tablicą, która również jest konwertowana na wskaźnik do jej pierwszego elementu.

zatem wyrażenia a i *a mają taką samą wartość jak ekspresji &a[0][0]