2010-01-10 11 views
10

mogę zadeklarować:Kiedy wskaźnik do tablicy jest użyteczny?

int (*ap)[N];

Więc ap jest wskaźnik na int tablicę o rozmiarze N. Dlaczego to jest zawsze przydatna? Jeśli przekazuję go do działania, co może z nim zrobić, gdyby nie mógł zrobić zwykłego wskaźnika do zawartości tablicy?

C Pytania i powiedzieć:

2,12: Jak mogę zadeklarować wskaźnik do tablicy?

Zazwyczaj nie chcesz.

+3

wskaźnik do wskaźnika do typu int jest jednak użyteczne. – Toad

+0

Nie sądzę, żebym kiedykolwiek potrzebował kodu przy użyciu wskaźnika do tablicy w ciągu 25 lat, które programowałem w C (użyłem tylko potrójnych wskaźników - SomeType *** var - kilka razy i zmienił kod, aby ich uniknąć tak szybko, jak tylko mogłem.) –

+1

@reinier: na pewno, ale nie zapytałem o to – zaharpopov

Odpowiedz

-3

I uważam, że wniosek z tej całej dyskusji jest nigdy. Nikt tak naprawdę nie wykazał użycia tego konstruktu, w którym coś innego nie działałoby w bardziej zrozumiały sposób.

2

To nie jest przydatne, naprawdę. Ale czasami używane są wskaźniki do tablic np. w Microsoft Windows API - widziałem tam wiele takich rzeczy.

+0

co do użytego w API wygranej? – zaharpopov

+0

Możesz google dla "wskaźnik do tablicy" inurl: msdn.microsoft.com ". Przykłady: http://msdn.microsoft.com/en-us/library/ms221359.aspx, http://msdn.microsoft.com/en-us/library/ms714816%28VS.85%29.aspx itd. –

+0

@ adam.wos: spojrzał na te linki - to wyglądało jak prawdziwe wskaźniki do tablic w C, tylko wskaźniki – zaharpopov

6

Jeśli zwiększysz wskaźnik, wskaże on początek następnej grupy N elementów.

To nie jest wielka sprawa, a jej użycie należy do programisty.

+4

Cholera, widziałeś, że to się kiedyś przydarzyło? – bmargulies

+1

Dobrze wiedzieć, że ktoś wie, że nie są one takie same =) –

+0

@bmargulies: Użyłem go dla tablicy sum kontrolnych MD5, gdzie każda suma kontrolna ma 16 bajtów. –

0

To będzie prawdopodobnie careen się w prywatną/kłótliwy, ale ...

Moim zdaniem, wskaźniki do tablic są w języku, bo wpadł do języka. Istnieją wskaźniki dla wszystkich innych deklarowalnych typów danych, więc są one również tutaj. Nigdy nie widziałem, żeby ktoś naprawdę się nad nimi zapracował. Hipotetycznie pozwalają na prototyp, który wymaga tablicy, a nie wskaźnika do elementu, ale ...

+0

... ale są to te same rzeczy (wskaźnik do (pierwszego) elementu i wskaźnik do tablicy)? :) –

+0

Oceniają w tej samej lokalizacji, ale typy są różne, a typy mają znaczenie. –

-1

Wydaje mi się, że bezużyteczne wydaje mi się wskazywanie tablicy. W języku C tablica jest już wskaźnikiem do bloku tego typu danych.

int (*ap)[N]; 
int **ipp; 

są tym samym typem danych (wskaźnik do wskaźnika na liczbę całkowitą). Jedyna różnica polega na tym, że istnieje przestrzeń dla liczb całkowitych N przydzielonych dla ap.

Nie ma potrzeby przekazywania tablicy przez wskaźnik do funkcji, np. W celu zmiany zawartości tablicy w ramach tej funkcji, ponieważ jest to już wskaźnik. Zasadniczo powiedziałbym, że jest to niepotrzebne i po prostu tworzy dodatkową potrzebę dereferencji wskaźnika, aby uzyskać dane w tablicy. Ale jestem pewien, że istnieje jakiś program lub algorytm, który mógłby znaleźć dla niego uzasadnione zastosowanie.

+1

Nie, to nie ten sam typ danych. Więc mówisz, że to w porządku zrobić 'ipp = ap;' i 'ap = ipp;' (zakładając, że wskaźniki wskazują na coś przydatnego)? –

+1

To nie to samo. Wypróbuj '++ ap' i' ++ ipp' i zobacz, co otrzymasz. –

+2

Tablice ** nie są ** wskaźnikami. Wyrażenie array * może być niejawnie przekształcone na typ wskaźnika w większości kontekstów, ale to nie to samo. W twoim przykładzie 'ap' i' ipp' nie są kompatybilnymi typami; nie można przypisać wartości 'ap' do' ipp' lub na odwrót (przynajmniej nie bez wyraźnego rzutowania). –

2

Istnieją sytuacje, w których chcesz przekazać lokalizację pamięci między programami. np. Windows API może oczekiwać, że przekażesz wskaźnik do struktury danych lub tablicy, w której programujesz w innym języku, powiedzmy C#. Windows API nie obchodzi, w jaki sposób język docelowy obsługuje tablice, dla Windows API jest to tylko strumień bajtów w pamięci, który wypełni go i odeśle do ciebie. Aby uniknąć typu missmatch typu cross-language, w niektórych przypadkach używamy wskaźnika do tablicy, a nie domyślnej nazwy tablicy jako wskaźnika. Ponadto nie jest gwarantowane, że nazwa niejawnej tablicy jest długim wskaźnikiem, niektóre kompilatory mogą ją zoptymalizować, aby była względną wartością dla segmentu. wskaźnik do tablicy gwarantuje, że jest on rzędu wielkości rejestru maszynowego i można wskazać lokalizację w dowolnym miejscu dostępnej pamięci RAM.

+0

czy możesz pokazać przykładowy kod używany? – zaharpopov

13

Wskaźnik do tablicy może być używany do dynamicznego przydzielania wielowymiarowej tablicy N, gdzie znane są wymiary N-1. Poniżej tworzy tablicę Nx3.

int (*ap)[3]; 
ap = malloc(N * sizeof(*ap)); 
/* can now access ap[0][0] - ap[N-1][2] */ 

@Adam E/Cruachan, To nie jest to samo, co wskaźnik do wskaźnika. ap jest pojedynczym wskaźnikiem do bloku pamięci zawierającego trzy kolejne liczby całkowite. ap ++ przesunie adres wskaźnika do następnego bloku trzech liczb całkowitych. dla int **pp;, pp wskazuje na wskaźnik całkowity, z których każdy może wskazywać na liczbę całkowitą w dowolnym miejscu w pamięci.

  +-----+    +------+ +-----+ 
ap ---> | int | vs. pp ---> | int* | -> | int | 
     | int |    +------+ +-----+ 
     | int |  pp+1 -> | int* | -\ 
     +-----+    +------+ \ +-----+ 
ap+1 -> | int |     : :  -> | int | 
     | int |        +-----+ 
     | int | 
     +-----+ 
      : : 
+0

ale prawdopodobnie ap jest po prostu tablicą 2d. – Pod

+2

Tak, ale to nie jest to samo co "int ap [4] [3];". Pozwala na dynamiczne przydzielanie drugiego wymiaru. –

+0

Ah Widzę, w takim razie przyznam się do błędu i wycofam odpowiedź. – Cruachan

2

Generalnie tylko raz zobaczysz wskaźnik do tablicy (T (*a)[N]) jest jako parametr funkcji, gdzie a rozumie się tablica 2d:

void foo(int (*a)[N], size_t count) 
{ 
    size_t i; 
    for (i = 0; i < count; i++) 
     a[i][j] = ...; 
    ... 
} 

void bar(void) 
{ 
    int arr[M][N]; 
    foo(arr, M); 
} 

Zauważ, że dla deklaracja parametru funkcja, int a[][N] jest równoważna int (*a)[N], ale to tylko prawdziwe dla deklaracji parametrów funkcja:

void foo (int a[][N], size_t count) {...} 

Wskaźniki do tablic generalnie nie są tak użyteczne, jak wskaźniki do typu bazowego, ponieważ musisz znać rozmiar tablicy, aby poprawnie zadeklarować do niej wskaźnik (wskaźnik do 10-elementowej tablicy int jest innego typu od wskaźnik do 20-elementowej tablicy int). Osobiście nie znalazłem dla nich większego pożytku w 20-letnich programach.

Należy pamiętać, że w większości kontekstów, wyrażenie tablicowe (takie jak arr powyżej) będzie miało swój typ niejawnie przekonwertowane z "N-elementowej tablicy T" na "wskaźnik do T" (z wyjątkiem sytuacji, gdy wyrażenie tablicy jest operandem sizeof lub &, lub tablica jest literałem łańcuchowym używanym jako inicjator w deklaracji). W tym przypadku typ arr w wywołaniu foo jest niejawnie konwertowany z "M-elementowej tablicy N-elementowej tablicy int" na "wskaźnik do N-elementowej tablicy int".

Biorąc pod uwagę oświadczenie T a[M][N], wszystkie z poniższych wyrażeń oceni w tej samej lokalizacji (adres pierwszego elementu tablicy), ale typy będą różne, jak pokazano poniżej:

 
Expression   Type    Implicitly converted to 
----------   ----    ----------------------- 
     a   T [M][N]   T (*)[N] 
     a[0]   T [N]    T * 
     &a   T (*)[M][N]   
    &a[0]   T (*)[N] 
    &a[0][0]   T * 
-1

Poniższy kod jest częścią mojego artykułu: Wskaźniki i tablic w C C++

Można to sprawdzić @http://pointersandarrays.blogspot.com/

Wskaźniki i 2D tablice

Po fragment kodu ilustruje jak zadeklarować i uzyskać dostęp do tablicy 2D. Pod tablicą 2D znajduje się tablica jednowymiarowa. Otrzymasz pewność tego po zagraniu z następującym kodem.

Code Snippet # 4


#include<iostream&rt; 
    using namespace std; 

    int main() 
    { 
    cout<< "Understanding Pointers and 2 D Arrays"<<endl; 
    cout<< "----------------------\n"<<endl; 

    //Declaration of a 2D Array. 
    int tab[3][5]; 
    //Total space required : 3*5 * sizeof(int) = 15 * sizeof(int) 
    //Funda : Since the amount of required space is known by compiler, contiguous 15 memory cells are allocated here.  
    //Hence the case is similar to a 1 D Array of size 15. Lets try this out! 

    //Array initialization using array name 
    for(int i=0; i<3;i++) 
    for(int j=0; j<5;j++) 
     tab[i][j]=i+2*j; 

    //Print array using array name 
    cout << "\nPrint array using array name ..."<<endl;  
    for(int i=0; i<3;i++) 
    { 
     for(int j=0; j<5;j++) 
     printf("%2d ",tab[i][j]); 
     printf("\n"); 
    } 

    //Print array using a pointer. Proof of 1 D array being allocated 
    cout << "\nPrint array using a pointer. Proof of 1 D array being allocated ..." << endl;  
    int *tptr; 
    tptr = &tab[0][0]; // pointer tptr points at first element of the array. 

    for(int i=0; i<15;i++) 
    printf("%d ",*(tptr+i)); 
    tptr = &tab[0][0]; 
    cout << "\nNotice that array is printed row by row in a linear fashion."<<endl; 
    return 0; 
    } 

Wyjście # 4:

Understanding Pointers and 2D Arrays 

Print array using array name ... 
0 2 4 6 8 
1 3 5 7 9 
2 4 6 8 10 

Print array using a pointer. Proof of 1 D array being allocated ... 
0 2 4 6 8 1 3 5 7 9 2 4 6 8 10 
Notice that array is printed row by row in a linear fashion. 

Powiązane problemy