C wskaźnik do tablicy / array of pointers disambiguation

Jaka jest różnica między następującymi deklaracjami:

int* arr1[8];
int (*arr2)[8];
int *(arr3[8]);

Jaka jest ogólna zasada rozumienia bardziej złożonych deklaracji?

Author: akashchandrakar, 2009-05-13

12 answers

int* arr[8]; // An array of int pointers.
int (*arr)[8]; // A pointer to an array of integers
Trzecia jest taka sama jak pierwsza.

Ogólna zasada to pierwszeństwo operatora. Może być jeszcze bardziej złożony, gdy Wskaźniki funkcji pojawiają się na obrazie.

 402
Author: Mehrdad Afshari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-13 18:37:30

Użyj programu cdecl , zgodnie z sugestią K & R.

$ cdecl
Type `help' or `?' for help
cdecl> explain int* arr1[8];
declare arr1 as array 8 of pointer to int
cdecl> explain int (*arr2)[8]
declare arr2 as pointer to array 8 of int
cdecl> explain int *(arr3[8])
declare arr3 as array 8 of pointer to int
cdecl>
Działa też w drugą stronę.
cdecl> declare x as pointer to function(void) returning pointer to float
float *(*x)(void )
 249
Author: sigjuice,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-03 14:47:04

Nie wiem, czy ma oficjalną nazwę, ale nazywam ją czymś Prawo-Lewo(TM).

Zacznij od zmiennej, następnie idź w prawo, w lewo i w prawo...i tak dalej.

int* arr1[8];

arr1 jest tablicą 8 wskaźników do liczb całkowitych.

int (*arr2)[8];

arr2 jest wskaźnikiem (blok nawiasów od prawej do lewej) do tablicy 8 liczb całkowitych.

int *(arr3[8]);

arr3 jest tablicą 8 wskaźników do liczb całkowitych.

To powinno pomóc w złożonych deklaracjach.

 118
Author: GManNickG,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-13 18:41:48
int *a[4]; // Array of 4 pointers to int

int (*a)[4]; //a is a pointer to an integer array of size 4

int (*a[8])[5]; //a is an array of pointers to integer array of size 5 
 24
Author: Sunil bn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-20 16:19:14

Odpowiedź dla dwóch ostatnich może być również odjęta od złotej reguły w C:

Deklaracja następuje po użyciu.

int (*arr2)[8];

Co się stanie, jeśli dereference arr2? Otrzymujesz tablicę 8 liczb całkowitych.

int *(arr3[8]);

Co się stanie, jeśli weźmiesz element z arr3? Dostajesz wskaźnik do liczby całkowitej.

To również pomaga w radzeniu sobie ze wskaźnikami do funkcji. Przykład sigjuice:

float *(*x)(void )

Co się stanie, gdy będziesz x? Otrzymujesz funkcję, którą możesz wywołać bez argumentów. Co się stanie, gdy to nazwiesz? Zwróci wskaźnik do float.

Pierwszeństwo operatora jest jednak zawsze trudne. Jednak używanie nawiasów może być również mylące, ponieważ deklaracja następuje po użyciu. Przynajmniej dla mnie intuicyjnie arr2 wygląda jak tablica 8 wskaźników do ints, ale w rzeczywistości jest odwrotnie. Trzeba się przyzwyczaić. Wystarczający powód, aby zawsze dodawać komentarz do tych deklaracji, jeśli zapytasz ja:)

Edit: example

Nawiasem mówiąc, natknąłem się na następującą sytuację: funkcję, która ma statyczną macierz i która używa arytmetyki wskaźnika, aby sprawdzić, czy wskaźnik wiersza jest poza granicami. Przykład:

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

#define NUM_ELEM(ar) (sizeof(ar) / sizeof((ar)[0]))

int *
put_off(const int newrow[2])
{
    static int mymatrix[3][2];
    static int (*rowp)[2] = mymatrix;
    int (* const border)[] = mymatrix + NUM_ELEM(mymatrix);

    memcpy(rowp, newrow, sizeof(*rowp));
    rowp += 1;
    if (rowp == border) {
        rowp = mymatrix;
    }

    return *rowp;
}

int
main(int argc, char *argv[])
{
    int i = 0;
    int row[2] = {0, 1};
    int *rout;

    for (i = 0; i < 6; i++) {
        row[0] = i;
        row[1] += i;
        rout = put_off(row);
        printf("%d (%p): [%d, %d]\n", i, (void *) rout, rout[0], rout[1]);
    }

    return 0;
}

Wyjście:

0 (0x804a02c): [0, 0]
1 (0x804a034): [0, 0]
2 (0x804a024): [0, 1]
3 (0x804a02c): [1, 2]
4 (0x804a034): [2, 4]
5 (0x804a024): [3, 7]

Zauważ, że wartość border nigdy się nie zmienia, więc kompilator może ją zoptymalizować. To różni się od tego, czego początkowo możesz chcieć użyć: const int (*border)[3]: który deklaruje border jako wskaźnik do tablicy 3 liczb całkowitych, które nie zmieni wartości dopóki zmienna istnieje. Jednak ten wskaźnik może być w dowolnym momencie wskazywany na dowolną inną taką tablicę. Chcemy zamiast tego takiego zachowania dla argumentu (ponieważ ta funkcja nie zmienia żadnej z tych liczb całkowitych). Deklaracja następuje po użyciu.

(p. s.: zapraszam do poprawy tej próbki!)

 14
Author: Hraban Luyat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-30 13:21:00
typedef int (*PointerToIntArray)[];
typedef int *ArrayOfIntPointers[];
 5
Author: Byron Formwalt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-14 17:51:34

Myślę, że możemy użyć prostej zasady ..

example int * (*ptr)()[];
start from ptr 

" ptr jest wskaźnikiem do " idź w prawo ..its") " now go left its a "(" come out go right "() " so "do funkcji, która nie przyjmuje argumentów "go left" i zwraca wskaźnik "go right" do tablica "idź w lewo" liczb całkowitych "

 2
Author: simal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-09 15:47:56

Z reguły prawe operatory jednoargumentowe (jak [], (), itp.) pierwszeństwo nad lewymi. Tak więc, int *(*ptr)()[]; będzie wskaźnikiem, który wskazuje na funkcję, która zwraca tablicę wskaźników do int (uzyskaj odpowiednie operatory tak szybko, jak to możliwe, gdy wyjdziesz z nawiasu)

 2
Author: Luis Colorado,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-19 13:34:06

Oto Jak to interpretuję:

int *something[n];

Uwaga dotycząca pierwszeństwa: operator array subscript ('[ ]') ma wyższy priorytet niż operator dereferencji ('*').

Więc tutaj zastosujemy "[] "przed"*", czyniąc twierdzenie równoważnym:

int *(something[i]);

Uwaga na sens deklaracji: int num oznacza (num) jest (int), int *ptr lub int (*ptr) oznacza, (wartość w ptr) jest an (int), co czyni ptr wskaźnikiem do int.

Można to odczytać jako, (wartość (wartość w i-tym indeksie czegoś)) jest liczbą całkowitą. Tak więc (wartość w i-tym indeksie czegoś) jest (wskaźnik integer), co sprawia, że coś jest tablicą wskaźników całkowitych.

W drugim,

int (*something)[n];

Aby to stwierdzenie miało sens, musisz być zaznajomiony z tym faktem:

Uwaga dotycząca reprezentacji wskaźnika tablicy: somethingElse [i] jest równoważne *(somethingElse + i)

Więc, zastępując coś na (*coś), otrzymujemy *(*something + i), która jest liczbą całkowitą zgodnie z deklaracją. Tak więc (*coś) dał nam tablicę, która czyni coś równoważnego (wskaźnik do tablicy).

 2
Author: nishantbhardwaj2002,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-11 18:52:17

Myślę, że druga deklaracja jest myląca dla wielu. Oto prosty sposób, aby to zrozumieć.

Pozwala mieć tablicę liczb całkowitych, tzn. int B[8].

Niech również będzie zmienna a, która wskazuje na B. teraz wartość na A to B, tzn. (*A) == B. Stąd a wskazuje na tablicę liczb całkowitych. W twoim pytaniu arr jest podobny do A.

Podobnie, w int* (*C) [8], C jest wskaźnikiem do tablicy wskaźników do liczby całkowitej.

 0
Author: nishantbhardwaj2002,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-12 11:46:19

Oto ciekawa strona, która wyjaśnia jak czytać złożone typy w C: http://www.unixwiz.net/techtips/reading-cdecl.html

 0
Author: Abhishek Jaisingh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-22 19:51:14

In pointer to an integer if pointer is incremented then it goes next integer.

W tablicy wskaźnika jeśli wskaźnik jest zwiększony, to przeskakuje do następnej tablicy

 -7
Author: Nikhil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-31 14:41:58