Pozostałe odpowiedzi są poprawne, ale żadna z nich nie podkreśla idei, że wszystkie trzy mogą zawierać tę samą wartość , a więc są w pewnym sensie niekompletne.
Powodem, dla którego nie można tego zrozumieć na podstawie innych odpowiedzi, jest to, że wszystkie ilustracje, choć pomocne i zdecydowanie rozsądne w większości przypadków, nie obejmują sytuacji, w której wskaźnik xwskazuje na siebie.
Jest to dość łatwe do skonstruowania, ale wyraźnie trudniejsze do zrozumienia. W poniższym programie zobaczymy, jak możemy wymusić identyczność wszystkich trzech wartości.
UWAGA: Zachowanie w tym programie jest nieokreślone, ale zamieszczam je tutaj wyłącznie jako interesującą demonstrację czegoś, co wskaźniki mogą zrobić, ale nie powinny .
#include <stdio.h>
int main () {
int *(*x)[5];
x = (int *(*)[5]) &x;
printf("%p\n", x[0]);
printf("%p\n", x[0][0]);
printf("%p\n", x[0][0][0]);
}
To kompiluje się bez ostrzeżeń w obu C89 i C99, a wynik jest następujący:
$ ./ptrs
0xbfd9198c
0xbfd9198c
0xbfd9198c
Co ciekawe, wszystkie trzy wartości są identyczne. Ale to nie powinno być zaskoczeniem! Najpierw podzielmy program.
Deklarujemy xjako wskaźnik do tablicy 5 elementów, gdzie każdy element jest wskaźnikiem typu do int. Ta deklaracja przydziela 4 bajty na stosie środowiska wykonawczego (lub więcej w zależności od implementacji; na moim komputerze wskaźniki mają 4 bajty), więc xodnosi się do rzeczywistej lokalizacji pamięci. W rodzinie języków C zawartość xjest po prostu śmieciami, czymś pozostałym po poprzednim użyciu lokalizacji, więc xsama nigdzie nie wskazuje - na pewno nie dotyczy przydzielonej przestrzeni.
Więc naturalnie możemy wziąć adres zmiennej xi gdzieś go umieścić, więc to jest dokładnie to, co robimy. Ale pójdziemy dalej i umieścimy to w samym x. Ponieważ &xma inny typ niż x, musimy wykonać rzut, aby nie otrzymywać ostrzeżeń.
Model pamięci wyglądałby mniej więcej tak:
0xbfd9198c
+------------+
| 0xbfd9198c |
+------------+
Zatem 4-bajtowy blok pamięci pod adresem 0xbfd9198czawiera wzorzec bitów odpowiadający wartości szesnastkowej 0xbfd9198c. Wystarczająco proste.
Następnie drukujemy trzy wartości. Pozostałe odpowiedzi wyjaśniają, do czego odnosi się każde wyrażenie, więc związek powinien być teraz jasny.
Widzimy, że wartości są takie same, ale tylko w sensie bardzo niskiego poziomu ... ich wzorce bitowe są identyczne, ale typ danych skojarzonych z każdym wyrażeniem oznacza, że ich interpretowane wartości są różne. Na przykład, jeśli wydrukowaliśmy przy x[0][0][0]użyciu ciągu formatu%d , otrzymalibyśmy ogromną liczbę ujemną, więc „wartości” są w praktyce różne, ale wzór bitowy jest taki sam.
To jest naprawdę proste ... na diagramach strzałki wskazują po prostu ten sam adres pamięci, a nie różne. Jednakże, chociaż byliśmy w stanie wymusić oczekiwany rezultat z niezdefiniowanego zachowania, to po prostu - niezdefiniowany. To nie jest kod produkcyjny, ale po prostu demonstracja w celu zapewnienia kompletności.
W rozsądnej sytuacji użyjesz mallocdo utworzenia tablicy 5 wskaźników int, a następnie do utworzenia ints, które są wskazywane w tej tablicy.malloczawsze zwraca unikalny adres (chyba że brakuje Ci pamięci, w takim przypadku zwraca NULL lub 0), więc nigdy nie będziesz musiał martwić się o takie wskaźniki odwołujące się do siebie.
Mam nadzieję, że to pełna odpowiedź, której szukasz. Nie należy się spodziewać x[0], x[0][0]i x[0][0][0]być równe, ale mogą być, jeśli zmuszony. Jeśli coś przeszło Ci przez głowę, daj mi znać, abym mógł wyjaśnić!
x[0],x[0][0]Ix[0][0][0]mają różne typy. Nie można ich porównać. Co masz na myśli!=?