Jaka jest różnica między zmienną a lokalizacją pamięci? [Zamknięte]


38

Ostatnio próbowałem wyjaśnić wskaźniki w sposób wizualny, jako fiszki.

Pytanie 001: To jest rysunek lokalizacji w pamięci komputera. Czy to prawda, że ​​jego adres to 0x23452? Czemu?

wprowadź opis zdjęcia tutaj

Odpowiedź: Tak, ponieważ 0x23452opisuje, gdzie komputer może znaleźć tę lokalizację.


Pytanie 002: Czy to prawda, że ​​znak bjest przechowywany w miejscu pamięci 0x23452? Czemu?

wprowadź opis zdjęcia tutaj

Odpowiedź: Nie, ponieważ postać afaktycznie jest w niej przechowywana.


Pytanie 003: Czy to prawda, że ​​wskaźnik jest przechowywany w miejscu pamięci 0x23452? Czemu?

wprowadź opis zdjęcia tutaj

Odpowiedź: Tak, ponieważ adres lokalizacji pamięci 0x34501jest w nim zapisany.


Pytanie 004: Czy to prawda, że ​​wskaźnik jest przechowywany w miejscu pamięci 0x23452? Czemu?

wprowadź opis zdjęcia tutaj

Odpowiedź: Tak, ponieważ adres innej lokalizacji pamięci jest w niej zapisany.


Teraz część, która mnie martwi. Inżynier oprogramowania wyjaśnił mi następujące wskazówki:

Wskaźnik to zmienna, której wartością jest adres pamięci innej zmiennej.

Na podstawie czterech fiszek, które wam wszystkim pokazałem, zdefiniowałbym wskaźniki w nieco inny sposób:

Wskaźnik to lokalizacja pamięci, której wartością jest adres pamięci innej lokalizacji pamięci.

Czy można bezpiecznie powiedzieć, że zmienna jest tym samym co lokalizacja pamięci?

Jeśli nie, to kto ma rację? Jaka jest różnica między zmienną a lokalizacją pamięci?


37
Jest niejawna tu założenie, że każdy czyta te zdjęcia będą wiedzieć intencję, że liczba szesnastkowa pod polem jest adres pamięci, i że a, 0x23453. nilitp. w nich są wartości. Może ci się to wydawać oczywiste, ale nie czułbym się komfortowo, udzielając decydujących odpowiedzi na te pytania, nie widząc, jak te pola są zdefiniowane. Naprawdę nie ma sposobu, aby dowiedzieć się, czy ana drugim obrazku jest znak, ciąg znaków (jeśli są inne) lub nazwa zmiennej. Jeśli jest to ciąg, to czy jest nilrównież ciąg? Czy wartość „zerowa”?
ilkkachu

39
Pytanie 1 jest złym pytaniem. Jest to coś, co musisz powiedzieć czytelnikom, zanim będą mogli odpowiedzieć na inne pytania. Zamiast pytania należy podać czytelnikowi informacje: „W poniższych pytaniach pola są lokalizacjami pamięci, a liczby szesnastkowe poniżej to ich adresy”.
17 z 26

15
Odpowiedź na pytanie 3 jest niemożliwa z uwagi na kontekst. Nie ma sposobu, aby powiedzieć na poziomie bajtów, w jaki sposób wartość przechowywana w pamięci jest interpretowana / wykorzystywana na poziomie aplikacji.
17 z 26

6
Warto zauważyć: wszystko, co tutaj piszesz, jest prawdziwe w języku C lub C ++, ale fałsz w zasadzie dla każdego języka, który nie ma wyraźnego odniesienia / dereferencji wskaźnika. Cała metafora zmiennych, które są szczelinami, których wartości są rozkładane, rozkłada się dla języka (takiego jak Python, Java, C #, Ruby, JavaScript lub wiele innych), w którym przypisanie powoduje, że zmienna wskazuje obiekt bez kopiowania go , a mutacje obiektu są widoczne przez wszystkie zmienne do niego wskazujące. Z tego powodu dokumentacja Pythona wykorzystuje alternatywną metaforę zmiennych jako metekorony zawieszone na obiektach.
Mark Amery,

19
BTW i wybacz mi, jeśli już to rozumiesz, ale wygląda na to, że może to być zamieszanie - ta notacja „0x23452” jest tylko sposobem na oznaczenie liczby w formacie szesnastkowym i jest to zrobione dla wygody. Ale to tylko liczba - w żaden sposób przedrostek 0x nie oznacza, że ​​jest wskaźnikiem, to, co jest przechowywane w pamięci, jest dosłownie tylko nieistotną liczbą (można nazwać lokalizacje pamięci zwykłymi liczbami dziesiętnymi). Znaczenie (tj. Sposób interpretacji liczby) pochodzi od języka - rodzaj zmiennej i sposób jej użycia.
Filip Milovanović

Odpowiedzi:


69

Zmienna to logiczna konstrukcja zgodna z przeznaczeniem algorytmu, podczas gdy lokalizacja pamięci to fizyczna konstrukcja opisująca działanie komputera. Ogólnie rzecz biorąc, w celu wykonania programu istnieje (wygenerowane przez kompilator) odwzorowanie między logicznym pojęciem zmiennej a pamięcią komputera.

(Nawet w języku asemblera mamy pojęcie zmiennych (logicznych) przechodzących do algorytmu i zamiaru oraz (fizycznych) lokalizacji pamięci, chociaż są one bardziej zbieżne w asemblerze.)

Zmienna jest pojęciem wysokiego (er) poziomu. Zmienna reprezentuje albo nieznane (jak w matematyce lub przypisaniu programistycznym) albo symbol zastępczy, który można zastąpić wartością (jak w programowaniu: parametry).

Lokalizacja pamięci to koncepcja niskiego (er) poziomu. Lokalizacja pamięci może być używana do przechowywania wartości, czasami do przechowywania wartości zmiennej. Rejestr procesora jest jednak innym sposobem przechowywania wartości niektórych zmiennych. Rejestry procesora są również lokalizacjami pamięci o niskim (er) poziomie, ale nie są lokalizacjami pamięci, ponieważ nie mają adresów, tylko nazwy.

W pewnym sensie zmienna jest mechanizmem abstrakcji do wyrażania zamiarów programu, podczas gdy lokalizacja pamięci jest fizyczną jednostką środowiska przetwarzania, która zapewnia przechowywanie i wyszukiwanie.

Pytanie 003: Czy to prawda, że ​​wskaźnik jest przechowywany w miejscu pamięci 0x23452? Dlaczego?

Nie możemy powiedzieć z całą pewnością. To, że istnieje tam wartość, która działałaby jako adres, nie oznacza, że ​​jest to ten adres, zamiast tego może być liczbą całkowitą (dziesiętną) 144466. Nie możemy przyjmować założeń dotyczących interpretacji wartości jedynie na podstawie tego, jak wyglądają one liczbowo.

Pytanie 004: Czy to prawda, że ​​wskaźnik jest przechowywany w miejscu pamięci 0x23452? Dlaczego?

To jest rzeczywiście dziwne pytanie. Oczekują pewnych założeń na podstawie pól, jednak zauważmy, że adresy zwiększają się o 1 dla każdego pola. W każdym nowoczesnym komputerze oznaczałoby to, że każda skrzynka może pomieścić bajt-bajt adresowalność jest normą od dziesięcioleci. Jednak bajt ma tylko 8 bitów i może mieścić się w zakresie od 0 do 255 (dla wartości bez znaku); ale pokazują znacznie większą wartość przechowywaną w jednym z tych adresów, więc są bardzo podejrzane. (Mogłoby to zadziałać, gdyby była to maszyna adresowana do słowa, ale nie mówi o tym i niewiele jest obecnie maszyn, chociaż niektóre maszyny edukacyjne są takie.)

Na podstawie czterech fiszek, które wam wszystkim pokazałem, zdefiniowałbym wskaźniki w nieco inny sposób:

Wskaźnik to lokalizacja pamięci, której wartością jest adres pamięci innej lokalizacji pamięci.

Chociaż zdarzają się sytuacje, w których takie myślenie jest prawidłowe, mieszacie tu metafory. Pojęcie zmiennej odnosi się do algorytmu i jego celu - nie trzeba zakładać, że wszystkie zmienne mają lokalizacje pamięci. Niektóre zmienne (zwłaszcza tablice) mają lokalizacje pamięci, ponieważ lokalizacje pamięci obsługują adresowanie (podczas gdy rejestry procesora można nazwać nieindeksowane).

Do wykonania istnieje logiczne mapowanie między zmiennymi i instrukcjami a lokalizacjami pamięci procesora i sekwencjami instrukcji procesora. Zmienna, której wartość nigdy się nie zmienia (np. Stała), niekoniecznie wymaga lokalizacji pamięci, ponieważ wartość może być odtwarzana do woli (np. W razie potrzeby dla sekwencji kodu generowanych przez kompilator).


4
Nawet 8-bitowe bajty wciąż nie są uniwersalne.
Deduplicator

14
@JimmyJames Rozważ przypadek forindeksu pętli, gdy kompilator zdecyduje się całkowicie rozwinąć pętlę. Nigdzie w wygenerowanym kodzie wyjściowym (czy to w zestawie, czy w kodzie maszynowym czy w kodzie bajtowym) nie ma miejsca w pamięci, w którym licznik pętli zostanie zapisany. Ale to wciąż zmienna.
dmckee

4
@JimmyJames, w przypadku wskaźnika w rozwiniętej pętli, tak, jeśli twój kod faktycznie używa wartości licznika, to musi być gdzieś załadowany , ale (a) to miejsce może być rejestrem, i (b) nie ma w zasadzie żadnego powodu, dla którego musiałaby to być ta sama lokalizacja na każdej iteracji rozwiniętej pętli.
Solomon Slow

3
Jeśli pętla robi coś takiego, jak kopiowanie tablicy o stałej długości sourcedo tablicy o równej długości, destto zakodowana pętla for (int i=0; i<8; ++i) dest[i] = source[i];może równie dobrze skompilować się do czegoś równoważnego powtórzeniu dest++ = source++;stosownej liczby razy. Sam licznik pętli nie jest widoczny (nawet w rejestrze), a tylko liczba powtórzeń informuje o stanie pętli.
dmckee

2
To rozróżnienie jest nieco mylone przez języki takie jak C, których semantyka jest ściśle oparta na abstrakcji maszyny, której pamięć składa się z numerowanych lokalizacji.
Michael Kay

20

Czy można bezpiecznie powiedzieć, że zmienna jest tym samym co lokalizacja pamięci?

Nie. Zmienna i lokalizacja pamięci to dwie abstrakty na dwóch różnych poziomach abstrakcji. Zmienna i wskaźniki są pojęciem wyższego poziomu na poziomie kodu / języka, lokalizacja pamięci jest pojęciem niższego poziomu na poziomie maszyny. Po skompilowaniu kodu w plik wykonywalny nie ma już żadnych zmiennych. Próba mówienia o lokalizacji pamięci i zmiennych w ten sposób jest kategorycznym błędem.

Zmienna może być zaimplementowana przy użyciu pamięci, ale nie zawsze, ponieważ kompilator może zoptymalizować obliczenia i wykonać wszystkie obliczenia dotyczące zmiennej całkowicie w rejestrach, lub może umieścić jedną zmienną w wielu lokalizacjach pamięci lub może użyć jednej pamięci lokalizacja dla wielu zmiennych.

Wskaźnik to lokalizacja pamięci, której wartością jest adres pamięci innej lokalizacji pamięci.

Ta seria kart jest tak zdezorientowana, że ​​nie są po prostu w porządku, ale nawet się nie mylą.


1
Once a code had been compiled into an executable, there's no longer any variables.Z tym chyba się nie zgadzam. To prawda, że ​​twoja zmienna, którą znasz (tj. Pod tą nazwą) już nie istnieje, ale twoje sformułowanie wydaje się sugerować, że skompilowany plik wykonywalny używa tylko adresów pamięci. To nie jest poprawne Twój skompilowany, ale nie wykonalny plik wykonywalny nie ma pojęcia, które adresy pamięci będą używane podczas wykonywania. Pojęcie zmiennej (tj. Odwołanie wielokrotnego użytku do dowolnego adresu pamięci, który zostanie przypisany w czasie wykonywania) wciąż istnieje w skompilowanym pliku wykonywalnym.
Flater

2
Lub kompilator może całkowicie zoptymalizować zmienną na różne sposoby. Przed obliczeniem czegoś, przycinanie niepotrzebnych zmiennych. Jeśli zmienna jest stała, to kompilator może skończyć na instrukcjach procesora, które używają stałych, i argumentowałbym, że to już nie jest liczone jako zmienna.
kutschkem

16

Zmienne są konstrukcjami językowymi . Mają nazwę, znajdują się w zakresie, mogą odnosić się do innych części kodu itp. Są logiczną jednostką. Kompilator może dowolnie implementować tę konstrukcję językową, o ile jest to możliwe do zaobserwowania zgodnie ze standardem językowym. W związku z tym zmienna nie musi być nigdzie przechowywana, jeśli kompilator może udowodnić, że nie jest potrzebny.

Lokalizacje pamięci są koncepcją sprzętową . Oznaczają miejsce w pamięci wirtualnej / fizycznej. Każda lokalizacja pamięci ma dokładnie jeden adres fizyczny i dowolną liczbę adresów wirtualnych, których można użyć do manipulowania nim. Ale zawsze w każdym miejscu pamięci jest przechowywany dokładnie jeden bajt.

Wskaźniki są szczególnym rodzajem wartości . Powiedzenie, że coś jest wskaźnikiem, przypomina powiedzenie, że coś jest rodzaju double. Oznacza, ile bitów jest użytych dla wartości i jak te bity są interpretowane, ale nie oznacza to, że ta wartość jest przechowywana w zmiennej, ani nie oznacza, że ​​ta wartość jest przechowywana w pamięci.


Podam przykład w C: Kiedy mam tablicę 2D int foo[6][7];i uzyskuję dostęp do jej elementu za pomocą foo[1][2], to foojest zmienna, która przechowuje tablicę. Kiedy foojest używany w tym kontekście, zostaje przekształcony we wskaźnik do pierwszego elementu tablicy. Ten wskaźnik nie jest przechowywany w żadnej zmiennej, ani nie jest przechowywany w pamięci, jego wartość jest generowana tylko w rejestrze procesora, używana, a następnie zapominana. Podobnie, wyrażenie foo[1]jest zamieniane w inny wskaźnik w tym kontekście, który ponownie nie znajduje się w zmiennej, nie jest przechowywany w pamięci, ale obliczany w CPU, używany i zapominany. Trzy zmienne pojęć , lokalizacja pamięci i wskaźnik to tak naprawdę trzy różne pojęcia.


Przy okazji, naprawdę miałem na myśli „zawsze w każdym miejscu pamięci jest przechowywany dokładnie jeden bajt”. Nie było tak w epoce kamienia komputerowego jakieś pięćdziesiąt lat temu, ale dotyczy to praktycznie całego używanego obecnie sprzętu. Ilekroć przechowujesz w pamięci wartość większą niż jeden bajt, w rzeczywistości używasz kilku kolejnych lokalizacji w pamięci. Tj. (Przy założeniu dużej kolejności bajtów endian) liczba 0x01234567 jest przechowywana w pamięci jako

+------+------+------+------+
| 0x01 | 0x23 | 0x45 | 0x67 |
+------+------+------+------+
    ^      ^      ^      ^
    |      |      |      |
 0x4242 0x4243 0x4244 0x4245

(Małe maszyny endianowe, takie jak architektura X86, przechowują bajty w odwrotnej kolejności). Dotyczy to również wskaźników: Wskaźnik na maszynie 64-bitowej jest przechowywany w ośmiu kolejnych bajtach, każdy z własnym adresem pamięci. Nie możesz spojrzeć na komórkę pamięci i powiedzieć: „Och, to jest wskaźnik!” Zawsze widzisz bajty tylko patrząc na pamięć .


Skąd komputer wie, kiedy grupa kolejnych lokalizacji pamięci zaczyna się i kończy?
progner

6
@progner Nie ma. To interpretuje bajty w pamięci zgodnie z instrukcją to wystąpią. Instrukcje te są również przechowywane w samej sekwencji bajtów. Dla CPU jedyną różnicą między bajtem zawierającym instrukcję, bajtem zawierającym znak, a bajtem zawierającym niektóre bity zmiennoprzecinkowe, jest sposób użycia tego bajtu. Jeśli bajt jest pobierany, ponieważ wskazuje na niego licznik programu, jest on używany jako instrukcja. Jeśli zostanie pobrany, ponieważ instrukcja mówi, aby załadować go do rejestru zmiennoprzecinkowego, jest on używany jako dane zmiennoprzecinkowe.
cmaster

7
@progner To była właściwie kluczowa innowacja architektury von-Neumana: Przechowywać zarówno instrukcje, jak i dane w tej samej pamięci, pozwalając na zmianę danych, które są później wykonywane jako więcej instrukcji. Pozwoliło to na samodzielną modyfikację kodu, ale także pozwala jądrze systemu załadować jakiś program do pamięci, a następnie nakazać CPU wykonanie tego programu. Przed von-Neumanem komputery takie jak maszyny Zuse otrzymywały instrukcje przez kanał, który był w pełni niezależny od danych, na których operowały.
cmaster

5

Pozwól, że skupię się na twoim prawdziwym pytaniu - „kto ma rację?” podczas porównywania tych dwóch instrukcji:

  • Wskaźnik to zmienna, której wartością jest adres pamięci innej zmiennej
  • Wskaźnik to lokalizacja pamięci, której wartością jest adres pamięci innej lokalizacji pamięci.

Odpowiedź na to pytanie jest przecząca . Pierwszy mówi o „adresie pamięci innej zmiennej”, ale zmienne niekoniecznie mają adresy pamięci, jak już wyjaśniono w innych odpowiedziach. Drugi mówi „wskaźnik jest miejscem pamięci”, ale wskaźnik jest dosłownie liczbą, która może być przechowywana w zmiennej, ale jak poprzednio, zmienna niekoniecznie ma adres pamięci.

Kilka przykładów dokładniejszych stwierdzeń:

  • „Wskaźnik to liczba reprezentująca adres pamięci miejsca w pamięci” lub

  • „Zmienna wskaźnikowa to zmienna, której wartością jest adres pamięci miejsca w pamięci.”

  • „Adres pamięci może zawierać wskaźnik reprezentujący adres pamięci lokalizacji pamięci”.

Zauważ, że czasami termin „wskaźnik” jest używany jako skrót do „zmiennej wskaźnika”, co jest w porządku, o ile nie prowadzi do zamieszania.


Możesz zmienić „inny” na „a”, ponieważ wskaźnik może wskazywać na siebie.
Pieter B

@PieterB: nitty, nitty ;-) nie jestem pewien, czy to naprawdę czyni to jaśniejszym, ponieważ chciałem tylko zmienić oryginalne sformułowanie w stopniu koniecznym do uczynienia ich sensownymi. Ale niestety dokonałem edycji.
Doc Brown,

Szczerze mówiąc, jeśli dostaniesz tego głupkowatego „ale wskaźnik jest dosłownie tylko liczbą” też nie jest poprawny, w rzeczywistości wskaźnik jest identyfikatorem potwierdzającym liczbę;) Lub przynajmniej musieliśmy znać specyfikę języka, aby się do nich dostać Detale.
Zaibis

2
Wskaźnik to wartość (liczba jest już zbyt specyficzna dla niektórych implementacji) potencjalnie odnosząca się do jakiegoś obiektu. Potencjalnie, ponieważ istnieją również wskaźniki zerowe, dzikie i wiszące, chociaż niektóre (a nawet wszystkie!) Z nich mogą być wykluczone przez używany język.
Deduplicator

2
@Deduplicator: masz rację, ale myślę, że model mentalny wskaźnika jako liczby jest wystarczający do celów tego pytania. Utrzymajmy więc prostotę.
Doc Brown,

5

Na pewno nie powiedziałbym, że wskaźnik to miejsce w pamięci, które zawiera adres. Po pierwsze, nie znam architektury, w której 0x23453mógłby zmieścić się jeden bajt. :) Nawet jeśli oddzielisz ręcznie rozróżnienie bajtów / słów, nadal masz problem z tym, że każda lokalizacja pamięci zawiera adres. Adresy to tylko liczby, a zawartość pamięci to tylko liczby.

Myślę, że sztuczka polega na tym, że „wskaźnik” opisuje ludzkie zamiary , a nie jakąś szczególną cechę architektury. Jest to podobne do tego, w jaki sposób „znak” lub „ciąg” nie jest konkretną rzeczą, którą można zobaczyć w pamięci - to również są tylko liczby, ale działają one jak ciągi, ponieważ w taki sposób są traktowane. „Wskaźnik” oznacza jedynie wartość przeznaczoną do wykorzystania jako adres.

Szczerze mówiąc, jeśli Twoim celem jest nauczenie określonego języka (Cel C?), Nie jestem pewien, czy wyciągnięcie klasycznej taśmy pamięci jest nawet tak przydatne. Mówisz już białe kłamstwa, pokazując wpisane wartości i wartości zbyt duże dla bajtu. Naucz semantykę, a nie mechanikę - kluczową wiedzę na temat wskaźników stanowi to, że zapewniają one pośrednie podejście , które jest niezwykle użytecznym narzędziem do zrozumienia.

Myślę, że dobrym porównaniem może być adres URL, który informuje, gdzie znaleźć dane, ale same dane nie są. Wysłuchaj mnie:

  • Rzadko zależy ci na tym, jaki faktycznie jest adres URL ; zdecydowana większość z nich jest połączona z nazwiskami. Wiele osób korzysta z Internetu, nie wiedząc dokładnie, w jaki sposób adres URL prowadzi do strony; niektóre osoby są całkowicie nieświadome adresów URL.

  • Nie każdy ciąg jest adresem URL ani nie może być używany jako adres URL.

  • Jeśli spróbujesz odwiedzić fałszywy adres URL lub stronę, która kiedyś istniała, ale została usunięta, pojawia się błąd.

  • Adres URL może wskazywać na obraz, jakiś tekst, trochę muzyki lub dowolną liczbę innych pojedynczych elementów - lub może wskazywać stronę zawierającą wiele różnych elementów. Często spotyka się mnóstwo stron o podobnych układach, ale różnych danych.

  • Jeśli tworzysz stronę internetową i chcesz odwoływać się do danych na innej stronie internetowej, nie musisz jej kopiować i wklejać; możesz po prostu zrobić link do niego.

  • Dowolna liczba innych stron może prowadzić do tego samego adresu URL.

  • Jeśli masz kolekcję podobnych stron, możesz utworzyć stronę indeksu, która zawiera linki do wszystkich z nich, lub możesz po prostu mieć link „następny” na dole strony 1, który prowadzi do strony 2 i tak dalej. Zalety i wady obu podejść są natychmiast oczywiste, zwłaszcza jeśli weźmiesz pod uwagę, co webmaster powinien zrobić, aby dodać lub usunąć strony w różnych miejscach.

Analogia ta sprawia, że bardzo jasne co wskaźniki są na , co jest kluczem do ich zrozumienia - w przeciwnym razie po prostu wydaje się arbitralne, skomplikowane i bezcelowe. Zrozumienie, jak coś działa, jest znacznie łatwiejsze, jeśli już wiesz, co to robi i dlaczego jest to przydatne. Jeśli już zinternalizowałeś, że wskaźnik jest jakąś czarną skrzynką, która mówi ci, gdzie jest coś jeszcze, a następnie dowiesz się o zawiłościach modelu pamięci, reprezentowanie wskaźników jako adresów jest dość oczywiste. Ponadto, nauczanie semantyki sprawi, że twoi uczniowie będą w znacznie lepszym miejscu do zrozumienia i wynalezienia innych form pośrednictwa - co jest dobre, gdy większość głównych języków w ogóle nie ma wskaźników!


every memory location contains an address- Każda lokalizacja pamięci ma adres. Nigdzie nie jest zawarty , może poza zmienną wskaźnikową.
Robert Harvey

@RobertHarvey każda lokalizacja pamięci (przynajmniej słowo) zawiera liczbę, którą można w prosty sposób interpretować jako adres. chodziło o to, że nic w sprzęcie nie odróżnia adresów od nieadresowych
Eevee

2

Wiem, że już zaakceptowałeś odpowiedź, a to pytanie ma już pięć odpowiedzi, ale jest kwestia, o której nie wspominają, jedna, o której myślę, że cię zaskoczyła. Podręczniki CS często starają się być agnostykami w kwestii wyboru języka programowania, co prowadzi do domyślnego założenia, że ​​terminologia stosowana do opisu rzeczy jest uniwersalna. To nie jest

W C jednostronny operator ampersand nazywany jest operatorem „adresu”. Programiści C nie zawahaliby się powiedzieć, że wyrażenie &xocenia na adres zmiennej x. Oczywiście oznaczają one „adres pamięci, w którym przechowywana jest wartość zmiennej x”, ale nikt nie jest pedantyczny w swobodnej rozmowie. W C słowo „wskaźnik” zwykle odnosi się do typu danych zmiennej, której adres ma adres pamięci. Lub równoważnie typ danych wartości. Ale niektórzy ludzie używają „wskaźnika” jako samej wartości.

W Javie wszystkie zmienne typu obiektowego lub tablicowego zachowują się bardzo podobnie do wskaźników C (z wyjątkiem arytmetyki wskaźników), ale programiści Java nazywają je referencjami, a nie wskaźnikami.

C ++ uważa odniesienia i wskaźniki za różne pojęcia. Są ze sobą powiązane, ale niezupełnie to samo, dlatego programiści C ++ muszą rozróżniać w rozmowach. Znak ampersand jest odczytywany jako „adres” w niektórych kontekstach, a „odniesienie do” w innych.

Wskaźnik to zmienna, której wartością jest adres pamięci innej zmiennej.

Tak mógłby to opisać programista C, używając „wskaźnika” w tym samym sensie, co „int”. (Podobnie jak w przypadku „wskaźnik zawiera adres pamięci, podczas gdy liczba int zawiera liczbę całkowitą z określonego zakresu.”)

Wskaźnik to lokalizacja pamięci, której wartością jest adres pamięci innej lokalizacji pamięci.

To dziwny sposób na powiedzenie tego, ponieważ wymaga bardzo luźnej i nieformalnej definicji „jest”.

Czy można bezpiecznie powiedzieć, że zmienna jest tym samym co lokalizacja pamięci?

Łatwiej byłoby powiedzieć, że adres pamięci to miejsce w pamięci, w którym przechowywana jest wartość zmiennej. (Oczywiście, nie wszystkie zmienne są przechowywane w pamięci, ze względu na optymalizacje kompilatora, ale dowolna zmienna, której adres zostanie wzięty, &xbędzie).


Ponieważ jesteśmy pedantyczni: adres, pod którym coś jest przechowywane. Oprócz adresu, który nie jest w stanie niczego przechowywać, często rzeczy są przechowywane w wielu sąsiadujących lokalizacjach, z których tylko jedna (zazwyczaj wybrana przez dość spójną zasadę) jest adresowana (i tylko przy użyciu jednego z potencjalnie wielu adresów).
Deduplicator

@Deduplicator Po pierwsze nie próbuję być pedantyczny.
gatkin

Standard C nawet formalnie rozróżnia formalnie między zmienne, które muszą ściśle podążać za krokami maszyny abstrakcyjnej w każdym „punkcie sekwencji” - ze względu na bezpieczeństwo wątków i pewne operacje niskiego poziomu na sprzęcie odwzorowanym w pamięci - od tych, które nie „ t, które można swobodnie przenieść do rejestru lub całkowicie zoptymalizować.
Davislor

@ Davislor: Standard C używa terminu „obiekt” w miejscach, w których inne specyfikacje języka używają „zmiennej”, a także do opisania innych rzeczy, które nie są zmiennymi. W niektórych dyskusjach można użyć terminu „zmienna” niezależnego od języka, ale z jakiegokolwiek powodu w normie brakuje terminu służącego do odróżnienia nazwanych rozłącznych przydziałów (zmiennych) od innych rodzajów obiektów, takich jak przydziały zagnieżdżone (elementy struct / union) lub uzyskane obiekty bez nazwy przez wskaźniki dereferencji. Nieformalnie „zmienna” jest świetnym terminem, ale Standard go nie używa.
supercat

@ superupat To nie jest poprawne. Standard C11 używa terminu „zmienna” ponad sto razy, z czego kilkadziesiąt to rzeczowniki, np. „Równoczesny dostęp do inicjowanej zmiennej, nawet za pomocą operacji atomowej, stanowi wyścig danych”.
Davislor,

1

Instrukcja Wskaźnik jest zmienną, której wartość jest adresem pamięci innej zmiennej, jest nadmiernie uproszczona. Ale zanim czytelnik zrozumie, czym dokładnie jest lokalizacja pamięci i czym różni się od zmiennej, zrozumie już, czym dokładnie jest wskaźnik, a zatem nie będzie już musiał polegać na tym niedokładnym wyjaśnieniu.

Instrukcja Wskaźnik jest lokalizacją pamięci, której wartość jest adresem pamięci innej lokalizacji pamięci, jest niepoprawna. Wartość wskaźnika nie musi być przechowywana w miejscu pamięci i jest dyskusyjna, jeśli wskaźnik musi wskazywać miejsce w pamięci, w zależności od zamierzonej definicji „pamięci”.

Jaka jest różnica między zmienną a lokalizacją pamięci

Lokalizacja pamięci jest jednym z wielu możliwych miejsc, w których można przechowywać dane. Te dane mogą być zmienną lub częścią zmiennej. Zmienne są sposobem na etykietowanie danych.


0

Ta odpowiedź dotyczy C i C ++; wydaje się to właściwe, ponieważ twoje pytanie dotyczy wskaźników, które są bardziej integralną częścią C / C ++ niż innych języków. Większość tego postu będzie dotyczyła większości skompilowanych języków bez skomplikowanego czasu działania (takich jak Pascal lub Ada, ale nie jak Java lub C #).

Podane już dobre odpowiedzi podkreślają, że zmienna jest konstrukcją językową na poziomie bardziej abstrakcyjnym niż pamięć fizyczna. Chciałbym jednak podkreślić, że abstrakcja ta ma pewne uzasadnienie i system:

Abstrakcja polega głównie na użyciu nazwy zamiast dosłownego adresu.

Podstawową ideą jest to, że zmienna jest nazwanym uchwytem dla wpisanego obiektu; obiekty w C / C ++ są zwykle w pamięci. Języki dodają następnie drobiazgów dotyczących zarządzania przez całe życie i zbierania danych dla konwersji typów. Pojęcie zmiennych jest bardziej abstrakcyjne niż adresy fizyczne, ponieważ tak naprawdę nie dbamy o wartość liczbową adresów lub dokładną lokalizację funkcji w pamięci. Po prostu nazywamy je, a później adresujemy według nazw, a kompilator, linker i system wykonawczy zajmują się drobiazgowymi szczegółami.

I nie udawaj, że C / C ++ są agnostyczne wobec pamięci: w końcu istnieje uniwersalny operator adresu. Tak, prawda, nie można pobrać adresu zmiennej C w klasie pamięci rejestrów; ale kiedy ostatnio go używałeś? Jest to szczególny wyjątek od ogólnej koncepcji, a nie całkowite odrzucenie argumentu. Przeciwnie, ogólna zasada mówi, że pobranie adresu zmiennej zmusza kompilator do stworzenia obiektu w pamięci, nawet jeśli nie zrobiłby tego inaczej (np. Ze stałymi). Koncepcja „nazwanego uchwytu” jest również dobrym paradygmatem dla referencji w C ++: Referencja to po prostu inna nazwa tego samego obiektu.

Kiedy napisałem wbudowany asembler dla 68k, miło było zobaczyć, jak można używać nazw zmiennych jako przesunięć adresujących rejestry (i można używać nazw zmiennych zadeklarowanych registerzamiast samych nazw rejestrów!). Dla kompilatora zmienna jest stałym przesunięciem adresu. Powtórzmy: Zmienne są nazwanymi uchwytami, zwykle dla obiektów w pamięci.


Wskaźniki są bardzo podstawową częścią języków C #, Java, JS i innych. Nazywanie ich inaczej nie zmienia tego, choć jest to dobry PR.
Deduplicator

@Deduplicator :-) Dobry stary Tony ...
Peter - Przywróć Monikę

0

Brzmi tak, jakby pytanie skierowane było do popularnego języka utworzonego przez rozszerzenie standardu C z dodatkową gwarancją „W przypadkach, gdy niektóre części standardu lub dokumentacja implementacji opisują zachowanie niektórych działań, a niektóre inne klasyfikują je jako niezdefiniowane , pierwsza część dominuje. ”, a także definicja„ zmiennej ”zgodna z użyciem tego terminu w innych językach.

W tym języku każdą lokalizację pamięci można postrzegać jako numerowaną skrzynkę pocztową, która zawsze zawiera pewną liczbę (zwykle osiem) bitów, z których każda może niezależnie wynosić zero lub jeden. Lokalizacje pamięci są zwykle zorganizowane w rzędach po dwa, cztery lub osiem. a niektóre operacje są przetwarzane jednocześnie w wielu kolejnych lokalizacjach pamięci. W zależności od komputera niektóre operacje, które działają na grupach składających się z dwóch, czterech lub ośmiu lokalizacji pamięci, mogą być ograniczone do operacji w lokalizacjach w jednym rzędzie. Ponadto, podczas gdy niektóre komputery mogą mieć jedno pomieszczenie ze kolejno ponumerowanymi skrzynkami pocztowymi, inne mogą mieć wiele rozłącznych grup ponumerowanych skrzynek pocztowych.

Zmienna identyfikuje zakres lokalizacji pamięci, które są z nią związane wyłącznie i typ, w jakim te lokalizacje pamięci powinny być interpretowane. Odczyt zmiennej spowoduje, że bity w powiązanych z nią lokalizacjach pamięci będą interpretowane w sposób odpowiedni dla typu zmiennej, a zapisanie zmiennej spowoduje ustawienie powiązanych bitów w sposób odpowiedni do jej typu i wartości.

Adres zawiera wszystkie informacje niezbędne do identyfikacji skrzynki pocztowej. Może być przechowywany jako zwykły numer lub jako rodzaj oznaczenia grupy wraz z numerem skrzynki pocztowej w tej grupie.

Zastosowanie &operatora do zmiennej da wskaźnik, który hermetyzuje adres i jego typ. Zastosowanie wskaźnika jednoargumentowego *lub []operatora do wskaźnika spowoduje, że bity skrzynek pocztowych zaczynające się od adresu w postaci enkapsulowanej zostaną zinterpretowane lub ustawione w sposób odpowiedni dla typu enkapsulowanego.


Brzmi, jakbyś zastanawiał się nad pytaniem.
Robert Harvey

0

Spóźniam się na to przyjęcie, ale nie mogę się powstrzymać przed włożeniem 2 centów.

Jaka jest obecnie różnica między wartościami przechowywanymi w tych lokalizacjach pamięci?

Czas 1

wprowadź opis zdjęcia tutaj

Czas 2

wprowadź opis zdjęcia tutaj

Prawidłowa odpowiedź: nic. Wszystkie są identycznymi wartościami prezentowanymi z różnymi interpretacjami ich znaczenia.

Skąd to wiem? Ponieważ to ja to wymyśliłem. Naprawdę tego jeszcze nie wiesz.

Napotykasz coś, co nazywam problemem poza pasmem . Jak poprawnie zinterpretować znaczenie tych wartości nie jest tutaj przechowywany. Ta wiedza jest przechowywana gdzie indziej. Jednak kiedy przedstawisz te wartości na papierze, zastosujesz tę interpretację. Oznacza to, że dodałeś informacje, które po prostu nie istnieją w tych lokalizacjach pamięci.

Na przykład wartości tutaj są identyczne, ale wiesz, że to prawda, jeśli masz rację, zakładając, że kodowanie znaków ASCII / UTF-8 jest sposobem, w jaki otrzymałem pierwszy, zamiast powiedzieć EBCDIC . Musisz także założyć, że drugi to szesnastkowe wyrażenia wartości liczbowych przechowywanych w tych lokalizacjach pamięci, które mogą być wskaźnikami do innych adresów, zamiast mówić o ciągach znaków, które zaczynają się od „0x”. : P

Nic przechowywane w tych lokalizacjach pamięci nie mówi, że którekolwiek z tych założeń jest prawidłowe. Informacje te mogą być przechowywane. Ale będzie przechowywany gdzie indziej.

To jest problem z prezentacją . Nie możesz wyrazić żadnej liczby bez uprzedniej zgody na jej przedstawienie. Możesz opierać się na założeniach, konwencjach i kontekście, ale jeśli głęboko się w nie zastanawiasz, gdy prezentacja nie jest wyraźnie zdefiniowana, jedyną naprawdę poprawną odpowiedzią jest „niewystarczająca ilość informacji”.


To jeszcze więcej zabawy, gdy ta sama pamięć jest używana do różnych stałych rzeczy w tym samym czasie.
Deduplicator

@Deduplicator True. To zawsze kojarzy mi się z reinterpretacją obsady c ++ . Te same bity widziały inaczej.
candied_orange

@Deduplicator lub, jeśli się nad tym zastanowić, związek in c
candied_orange
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.