2014-11-13 18 views
5

Biorąc pod uwagę definicję tablicy w C: int a [2] [3] [4] [5], a także adres [0] [0] [ 0] [0] to 1000 jaki jest adres [1] [1] [1] [1], zakładając, że int zajmuje 4 bajty.Znajdź adres indeksu w tablicy w C

mam:

(3 * 4 * 5 * 4bytes) + (4 * 5 * 4bytes) + (5 * 4bytes) + 4bytes = 344

344 + 1000 = 1344 Lokalizacja z [1] [1] [1] [1]

, ale nie mam pojęcia, czy mam rację. Ale moja matematyka wydawała mi się rozsądna.

+0

Brzmi nieźle. – JS1

Odpowiedz

3

Wystarczy wydrukować adres zmiennej każdy będzie go zobaczyć !:

#include <stdio.h> 

int main() { 

    int a[2][3][4][5]; 

    printf ("Size of int %d\n", sizeof(int)); 

    printf("Adress of the frist element \t%p\n", &a[0][0][0][0]); 
    printf("Adress of x element \t\t%p\n", &a[1][1][1][1]); 

    printf ("In decimal: \t\t\t%d\n", &(a[0][0][0][0])); 
    printf ("In decimal: \t\t\t%d\n", &(a[1][1][1][1])); 

    printf("Difference between the adresses %d", (char *)&a[1][1][1][1] - (char *)&a[0][0][0][0]); 




    return 0; 

} 

Po tym można sprawdzić, czy gdzie prawo!

I jak widzisz swoje prawo! to 334

+0

Twój drugi 'printf' podaje adres' a [1] [1] [1] [0] ', a nie' a [1] [1] [1] [1] '. Dlaczego nie być prostym w tym, co próbujesz zrobić i napisać '& a [0] [0] [0] [0]'? –

+0

@RedAlert Wups zapomniałem 1 wymiar! dzięki – Rizier123

+0

'% d' ze wskaźnikiem jest problematyczne (szczególnie jeśli int ma 32bit, a wskaźnik ma 64bit), rozważ użycie [uintptr_t] (http://stackoverflow.com/questions/5795978/string-format-for-intptr-t -i-uintptr-t) –

0

Coś w tym jest dość prosty do sprawdzenia (a):

#include <stdio.h> 

int main (void) { 
    int a[2][3][4][5]; 

    // Ignore incorrect format specifiers for now. 

    printf ("%d\n", sizeof(int)); 
    printf ("%d\n", &(a[0][0][0][0])); 
    printf ("%d\n", &(a[1][1][1][1])); 
    printf ("%d\n", (int)&(a[1][1][1][1]) 
        - (int)&(a[0][0][0][0]) 
        + 1000); 

    return 0; 
} 

i wyjście to:

4 
2665056 
2665400 
1344 

Note konwersje tych wskaźników do int wartości w tym końcowym printf. Bez tego, 1000 będzie skalowany jako int *, podając niewłaściwą wartość.

Tak, tak, ostatecznie, twoje rozumowanie jest poprawne.


(a) To nie zawsze przypadek, ponieważ niektóre aspekty języka C mogą różnić się w poprzek wdrożeń (zachowanie implementacji określony) lub w jakikolwiek sposób jest chcą (niezdefiniowane zachowanie).

Szczęśliwie, układ tablic jest podano szczegółowo w normie, w C11 6.5.2.1 Array subscripting:

2/Wyrażenie przyrostek następnie wyrażeniem w nawiasach kwadratowych [] jest indeksowana oznaczenie elementu tablicy obiekt. Definicja operatora indeksu dolnego jest taka, że ​​E1[E2] jest identyczna z. Ze względu na zasady konwersji, które stosuje się do binarnego + operatora, jeśli E1 Przedmiotem tablica (równoważnie, wskaźnik do pierwotnego elementu obiektu tablicy) i E2 jest liczbą całkowitą, E1[E2] oznacza element E2-th z E1 (licząc od zera).

3/Kolejni operatorzy indeksów podrzędnych wyznaczają element wielowymiarowego obiektu tablicowego. Jeśli E jest tablicą n-wymiarową (n> = 2) o wymiarach i * j * ... * k, to E (używane jako inne niż l-wartość) jest konwertowane na wskaźnik na tablicę (n-1) o wymiarach j * ... * k.Jeśli jednoargumentowy operator * zostanie zastosowany do tego wskaźnika jawnie lub niejawnie w wyniku indeksowania, wynikiem jest tablica odniesienia (n-1), która sama jest przekształcana na wskaźnik, jeśli jest używana jako inna niż l-wartość. Wynika z tego, że tablice są przechowywane w kolejności rzędowej (ostatni indeks zmienia się najszybciej).

+1

ten wynik wydaje się dziwny, '2665400 - 2665056 + 1000' nie jest' 1086'. Wyobrażam sobie, że kompilator myśli, że próbujesz wykonać arytmetykę wskaźnika. –

+1

@RedAlert, tak, właśnie to zauważyłem i pomyślałbyś, że ktoś z tak dużą liczbą C pod pasem, jak ja, wiedziałby to z góry :-) Zmodyfikowany, aby naprawić. – paxdiablo

3

Twoja matematyka jest poprawna. Można to sprawdzić poprzez odjęcie dwa adresy, ale nie zapominaj, że wskaźnik arytmetyka będzie rozpoznawał rozmiaru czcionki, więc trzeba rzucić adresy do char, który ma rozmiar bajtu:

(char*)&a[1][1][1][1] - (char*)&a[0][0][0][0] 

co daje różnica w bajtach. Następnie dodaj adres początkowy i uzyskaj odpowiedź.