2010-09-28 13 views
8

To właśnie dotarło do mnie, że nie wiem jak zainicjować wskaźnik do wskaźnika z braku wartości wskaźnika z jednej instrukcji w C++:Inicjowanie wskaźnik do wskaźnika za pomocą wielu operatorów adresowych w C lub C++

int a = 1; 
int** ppa = &&a; //Does not compile 
int** ppa = &(&a); //Does not compile 
int* pa = &a; //Works but is a 
int** ppa = &pa; //Two step solution 

Czy brakuje mi czegoś, czy dwa stwierdzenia to jedyny sposób, aby to zrobić?

+3

Dlaczego uważasz, że potrzebujesz wskaźnika do wskaźnika, w tym przypadku? – SingleNegationElimination

+0

możliwy duplikat [Jak wskaźnik do wskaźników działa w C?] (Http://stackoverflow.com/questions/897366/how-do-pointer-topointpoint-work-in-c) –

+1

@Jens Gustedt, to nie jest duplikatem. Powiązane pytanie pyta o wskaźniki w ogóle. To pytanie dotyczy konkretnego przypadku. –

Odpowiedz

12

jeśli chcesz wskaźnik do wskaźnika, wskaźnik, który chcesz zaznaczyć, musi znajdować się gdzieś w pamięci, więc myślę, że nie może być „rozwiązanie krok”, ponieważ potrzebujesz zmiennej wskaźnika, na którą możesz wskazać.

(Uwaga: To zdanie nie ma być próbę językową używać „punkt”, jak często jak to możliwe w jednym zdaniu :-))

14

Nie można uzyskać wskaźnika do tymczasowego. &a powoduje wyświetlenie wartości r. Dopuszczalne jest nie posiadanie faktycznego adresu.

+1

To jest w 100% poprawne, ale przyjąłem odpowiedź Philipa, ponieważ idzie ona do uzasadnienia, dlaczego tak jest, zamiast wskazywać na standard. –

2

Chcesz wskaźnik (nazwij go PP) do wskaźnika (nazywasz to P)?

Następnie musi istnieć P. Co oznacza, że ​​musisz to zadeklarować.

Oczywiście kompilator zawiedzie pod adresem &&a - ponieważ nie można pobrać adresu adresu. Możesz może wziąć adres wskaźnika - ale musisz najpierw zadeklarować wskaźnik.

Zatem:

int a = 1; 
int *P = &a; 
int **PP = &P; 
+1

Parser kończy się niepowodzeniem w '&& a' nie dlatego, że nie można pobrać adresu adresu, ale ponieważ' && 'jest pojedynczym tokenem, który nie jest ważny w tym momencie deklaracji. 'int ** ppa = x &&a;' może być poprawną inicjacją dla odpowiednio wpisanego 'x' i odpowiednio przeciążonego' && '(evil!), ale nie będzie to adres adresu. –

0

Kiedy należy wykonać następujące czynności:

char a; 
char* b = &a; 
char** c = &b; 

Przede wszystkim teraz istnieje na stosie. Ma oczywiście adres pamięci (tj. Pozycję stosu) to jest to, co przypisujesz b. b teraz również istnieje na stosie, a następnie możesz przekazać jego adres pamięci do c. Nie możesz jednak wziąć adresu adresu wartości bez stosu pośredniego, ponieważ nie istnieje bez jawnego utworzenia go w pierwszej kolejności.

-1

ten może działać:

Int ** ppa = & (int *) {& a};

+0

Hmm, nie ma, tworzy tymczasowy – fileoffset

7

Wiele innych ma rację: wskaźnik do wskaźnika musi wskazywać na coś. Jednak w C99 można oszukać za pomocą compound literals:

int a = 1; 
int **ppa = &(int *){ &a }; 

złożone literały są w zasadzie tylko nienazwane obiekty i mają te same zasady przechowywania jak normalnych obiektów. (Ale nie można podać czasu trwania składowej stałej literowej czasu składowania ze słowem kluczowym static). Można nawet zagnieździć je tak można przepisać poprzedni przykład na jednej linii:

int **ppa = &(int *) { &(int) { 1 } }; 
+0

To najprawdopodobniej będzie niezdefiniowanym zachowaniem i prawdopodobnie spowoduje awarię aplikacji przy pierwszym użyciu wskaźnika. Literał złożony jest tymczasowy, a kompilator może ponownie wykorzystać tę przestrzeń, więc '' ppa' wskazuje na 'i a' podczas wykonywania drugiej linii, ale może wskazywać na cokolwiek innego później. –

+1

@David Rodriguez: Nie, twoje są złe. Literał złożony będzie miał taki sam czas przechowywania jak "a" i "ppa": Statyczny, gdy poza funkcją, automatycznie na czas bloku zamykającego. Patrz C99 6.5.2.5 (6). – schot

+1

Masz całkowicie rację. Powinienem był sprawdzić standard zanim przejdę do komentarza ... Jeśli w którymkolwiek momencie zmienisz odpowiedź, komentarz, a ja zmienię -1 na +1, nie pozwala mi to teraz zmienić. W każdym razie, zależnie od tego, co chcesz zrobić ze wskaźnikiem, jest * tak niebezpieczne * jak rozwiązanie pośredniej zmiennej. –

5

C++ 03 [Section 5.3.1] mówi

Wynik jednoargumentowego & operatora jest wskaźnikiem do jej operand. Operand będzie mieć wartość lvalue lub kwalifikowany identyfikator.W pierwszym przypadku, jeśli typ wyrażenia „T”, typ wynik jest „wskaźnik T”

w &&a, & operator nie może być zastosowany do wyniku &a ponieważ wynik nie jest lvalue.

przeczytać również this wątek

2

Adres jest liczbą. Ma tylko swój własny adres, jeśli jest trzymany w zmiennej, tj. Wskaźniku. Więc

int *i1 = &a; 

sens, ale

int **i2 = &&a; 

nie ma sensu. Jednak

int **i2 = &i1; 

ma sens. Ma sens?

+1

Twoja terminologia jest błędna. Adres operatora * nie * daje wskaźnik, patrz [ISO03, 5.3.1 expr.unary.op §2]. Często wywołujemy wskaźnik * wartości * "adresy" i wskaźnik * zmienne * "wskaźniki", ale mówiąc ściśle, jest to błędne. – fredoverflow

+0

Używana terminologia jest powszechnie używana. Wartość wskaźnika w rozumieniu Standardu to adres w jakimkolwiek sensie, który z kolei jest w jakimś sensie liczbą. Aby umieścić to, co powiedziałem w inny sposób, i nie daje * zmiennej, * więc nie daje niczego, czego adres może być zajęty. – EJP

0

Problem polegający na tym, że robisz coś takiego jak &&a;, to pytanie o "adres adresu a".

To nie ma sensu. Możemy uzyskać adres a, ale to nie daje nam zmiennej, którą możemy wziąć pod adres. To po prostu daje nam wartość wskaźnika. Dopóki ta wartość nie zostanie gdzieś zapisana, nie możemy wziąć jej adresu.

Jeśli masz kod taki jak 2+2, wynik również nie ma adresu. Jest to tylko wartość 4, ale nie została jeszcze nigdzie zapisana, więc nie możemy wziąć adresu. Po zapisaniu w zmiennej int możemy pobrać adres tej zmiennej.

Zasadniczo problemem jest różnica między wartościami i zmiennymi. Wartość to po prostu liczba (lub znak lub inne dane). Zmienna jest miejscem w pamięci, w którym przechowywana jest wartość. Zmienna ma adres, ale wartość nie.

W C++ - mów, jest to różnica między wartościami r i l. Wartość r jest zasadniczo tymczasowa, zwykle jest wartością zwracaną przez inną operację (taką jak operator & w twoim przypadku), ale nie została jeszcze nigdzie zapisana.

Po zapisaniu w zmiennej otrzymasz wartość l, a wartości l mają adres, który możesz wybrać.

Tak, potrzebujesz dwóch oddzielnych instrukcji. Najpierw bierzesz adres, a potem gdzieś go przechowujesz. A potem możesz wziąć adres tego "gdzieś".

+0

Twoja terminologia jest błędna. Adres operatora * nie * daje wskaźnik, patrz [ISO03, 5.3.1 expr.unary.op §2]. Często wywołujemy wskaźnik * wartości * "adresy" i wskaźnik * zmienne * "wskaźniki", ale mówiąc ściśle, jest to błędne. – fredoverflow

+0

@Fred: Wystarczająco. Podejrzewałem, że wpadnę w kłopoty. ;) To nauczy mnie próbować przeformułować semantykę C++: p – jalf

+0

Naprawiono to trochę. Mam nadzieję, że mam najbardziej mylące kawałki. – jalf

Powiązane problemy