Яка різниця між змінною та пам'яттю? [зачинено]


38

Останнім часом я намагаюся пояснити покажчики візуально, як картки.

Питання 001: Це малювання місця в пам'яті комп'ютера. Чи правда, що його адреса 0x23452? Чому?

введіть тут опис зображення

Відповідь: Так, оскільки 0x23452описується, де комп'ютер може знайти це місце.


Питання 002: Чи правда, що символ bзберігається всередині пам'яті 0x23452? Чому?

введіть тут опис зображення

Відповідь: Ні, тому що персонаж aфактично зберігається всередині нього.


Питання 003: Чи правда, що вказівник зберігається всередині пам'яті 0x23452? Чому?

введіть тут опис зображення

Відповідь: Так, тому що адреса місцезнаходження пам'яті 0x34501зберігається всередині неї.


Питання 004: Чи правда, що вказівник зберігається всередині пам'яті 0x23452? Чому?

введіть тут опис зображення

Відповідь: Так, оскільки адреса іншого місця пам'яті зберігається всередині нього.


Тепер за ту частину, яка мене хвилювала. Програмний інженер пояснив мені покажчики так:

Покажчик - це змінна, значення якої - адреса пам'яті іншої змінної.

На основі чотирьох карт, які я вам показав, я б визначив вказівники дещо по-іншому:

Вказівник - це місце пам'яті, значенням якого є адреса пам'яті іншого місця пам'яті.

Чи безпечно сказати, що змінна - це те саме, що і місце пам'яті?

Якщо ні, то хто прав? Яка різниця між змінною та пам'яттю?


37
Там це неявне припущення про те, що тут кожен читає ці фотографії будуть знати ваші наміри , що число шістнадцяткове під полем є адреса пам'яті, і що a, 0x23453. nilі т.д. речі всередині них - це значення. Це може здатися вам очевидним, але мені не було б зручно давати вирішальні відповіді на ці питання, не бачачи того, як визначені ці поля. Дійсно неможливо дізнатися, чи є aна другому зображенні символ, рядок (якщо вони є різними) чи ім'я змінної. Якщо це рядок, то це nilтакож рядок? Або "нульове" значення?
ilkkachu

39
Питання 1 - це погане питання. Це те, що вам потрібно сказати читачам, перш ніж вони зможуть відповісти на інші запитання. Замість запитання читачеві слід надати інформацію: "У наступних питаннях поля знаходяться в пам'яті, а шістнадцяткові номери - їх адреси".
17 з 26

15
На питання 3 неможливо відповісти, враховуючи контекст. Немає можливості сказати на рівні байтів, як значення, що зберігається в пам'яті, інтерпретується / використовується на рівні програми.
17 з 26

6
Варто зауважити: все, що ви тут пишете, стосується C або C ++, але неправдиво для будь-якої мови, яка не має явного вказівника на посилання / перенаправлення. Вся метафора змінних, що є слотами, значення яких ставлять на розбиття для мови (наприклад, Python, Java, C #, або Ruby, JavaScript чи багатьох інших), коли присвоєння просто робить змінну точку об'єкта, не копіюючи його , а мутації до об'єкта видно через усі змінні, що вказують на нього. З цієї причини документація Python використовує альтернативну метафору змінних як теги імен, що висять на об'єктах.
Марк Амері

19
До речі, і вибачте мене, якщо ви вже це розумієте, але, схоже, це може бути точкою плутанини - це позначення "0x23452" - це лише спосіб позначити число в шістнадцятковому форматі, і це робиться просто для зручності. Але це просто число - префікс 0x жодним чином не позначає, що це покажчик, що зберігається в пам'яті - це буквально просто безглузде число (ви можете позначити місця пам'яті простими десятковими цілими числами). Значення (тобто, як слід інтерпретувати число) походить від мови - тип змінної та спосіб її використання.
Філіп Мілованович

Відповіді:


69

Змінна - це логічна конструкція, яка відповідає наміру алгоритму, тоді як місце пам'яті - це фізична конструкція, яка описує роботу комп'ютера. Взагалі, для виконання програми існує (створений компілятором) зіставлення між логічним поняттям змінної та зберіганням комп'ютера.

(Навіть у мові складання у нас є поняття (логічні) змінні, що переходять до алгоритму та наміру, та до (фізичної) пам'яті, хоча вони в більшій кількості пов'язані в складанні.)

Змінна - це концепція високого (ер) рівня. Змінна являє собою або невідому (як в математиці, або програмуванні) або держатель місця, яку можна замінити значенням (як у програмуванні: параметри).

Місце пам'яті - це концепція низького рівня (er) рівня. Місце пам'яті може використовуватися для зберігання значення, іноді для зберігання значення змінної. Однак регістр ЦП - це ще один спосіб збереження значення певної змінної. Регістри процесора також є місцями зберігання низького рівня (er), але вони не є пам'яттю, оскільки вони не мають адреси, а лише імена.

У певному сенсі змінна є механізмом абстрагування для вираження намірів програми, тоді як місце пам'яті - це фізична сутність обробного середовища, яка забезпечує зберігання та пошук.

Питання 003: Чи правда, що вказівник зберігається всередині пам'яті 0x23452? Чому?

Ми не можемо сказати, напевно. Тільки тому, що там є значення, яке буде працювати як адреса, не означає, що це адреса, натомість це може бути ціле число (десятковий) 144466. Ми не можемо робити припущення щодо інтерпретації значень лише на основі того, як вони відображаються чисельно.

Питання 004: Чи правда, що вказівник зберігається всередині пам'яті 0x23452? Чому?

Це справді дивне питання. Вони очікують деяких припущень, заснованих на полях, однак зазначимо, що адреси збільшуються на 1 для кожного поля. У будь-якому сучасному комп’ютері це означатиме, що кожне поле може містити байт - байт-адресацію, є нормою вже десятиліттями. Однак байт становить лише 8 біт і може становити від 0 до 255 (для непідписаних значень); але вони виявляють набагато більшу цінність, що зберігається в одній з цих адрес, так що дуже підозріло. (Це може спрацювати, якби це машина, адресована словом, але це не говорить про це, і сьогодні мало машин, хоча деякі навчальні машини такі.)

На основі чотирьох карт, які я вам показав, я б визначив вказівники дещо по-іншому:

Вказівник - це місце пам'яті, значенням якого є адреса пам'яті іншого місця пам'яті.

Хоча бувають ситуації, коли таке мислення правильне, ви тут змішуєте метафори. Поняття змінної переходить до алгоритму та його наміру - не потрібно вважати, що всі змінні мають місце пам'яті. Деякі змінні (особливо масиви) мають місця пам'яті, оскільки місця пам'яті підтримують адресацію (тоді як регістри процесора можуть бути названі лише неіндексованими).

Для виконання існує логічне відображення між змінними та операторами та місцями пам'яті процесора та послідовностями інструкцій процесора. Змінна, значення якої ніколи не змінюється (наприклад, константа), навіть не обов'язково вимагає розташування пам'яті, оскільки значення може бути відтворене за бажанням (наприклад, як це потрібно для кодових послідовностей, згенерованих компілятором).


4
І навіть 8-бітні байти все ще не є універсальними.
Дедуплікатор

14
@JimmyJames Розгляньте випадок forіндексу циклу, коли компілятор вирішить повністю розкрутити цикл. Ніде в створеному вихідному коді (будь то збірка, машинний код або байт-код) немає місця пам'яті, в якому зберігається лічильник циклу. Але це все-таки змінна.
dmckee

4
@JimmyJames, Що стосується покажчика розкрученого циклу, то так, якщо ваш код фактично використовує значення лічильника, його потрібно десь завантажити , але (a) це місце може бути реєстром, і (b) немає принципових причин, чому це повинно бути однакове місце розташування на кожній ітерації розкрученого циклу.
Соломон повільно

3
Якщо цикл виконує щось на кшталт копіювання масиву фіксованої довжини в масив sourceрівної довжини, destцикл закодований, що for (int i=0; i<8; ++i) dest[i] = source[i];може цілком скластись до чогось еквівалентного повторення dest++ = source++;відповідного числа разів. Сам лічильник циклу ніде не підтверджується (навіть не реєструється), і лише кількість повторень говорить вам про стан циклу.
dmckee

2
Відмінність дещо плутається на таких мовах, як C, семантика яких тісно заснована на абстрагуванні машини, пам'ять якої складається з пронумерованих місць.
Майкл Кей

20

Чи безпечно сказати, що змінна - це те саме, що і місце пам'яті?

Ні. Змінна та пам'ять - це дві абстракції на двох різних рівнях абстракції. Змінні та покажчики - це концепція вищого рівня на рівні коду / мови, місце пам'яті - це концепція нижчого рівня на машинному рівні. Після того, як код був зібраний у виконуваний файл, змінних більше немає. Спроба розповісти про розташування пам'яті та змінні таким чином - це категорична помилка.

Змінна може бути реалізована за допомогою пам'яті, але не завжди, оскільки компілятор може оптимізувати обчислення та робити всі обчислення, що стосуються змінної, повністю у регістрах, або вона може розміщувати одну змінну в декількох місцях пам'яті, або вона може використовувати одну пам'ять розташування для кількох змінних.

Вказівник - це місце пам'яті, значенням якого є адреса пам'яті іншого місця пам'яті.

Ця серія флешкартів настільки заплутана, що вони не просто не праві, але навіть не помиляються.


1
Once a code had been compiled into an executable, there's no longer any variables.З цим я, безперечно, не згоден. Це правильно, що ваша змінна, як ви її знаєте (тобто за цим ім'ям), вже не існує, але, як видається, ваша фразова думка говорить про те, що для складеного виконуваного файлу використовуються лише адреси пам'яті. Це не правильно. Ваш компільований, але не виконаний виконуваний файл не має уявлення, які адреси пам'яті він буде використовувати при його виконанні. Поняття змінної (тобто багаторазового посилання на ту адресу пам'яті, яка буде призначена під час виконання) все ще існує всередині компільованого виконуваного файлу.
Флатер

2
Або компілятор міг оптимізувати змінну повністю далеко, різними способами. Попередньо обчисливши щось, обрізаючи непотрібні змінні. Якщо змінна є постійною, то компілятор може в кінцевому підсумку використовувати інструкції процесора, які використовують константи, і я заперечую, що перестала вважатись такою змінною ніде.
kutschkem

16

Змінні - це мовні конструкції . Вони мають ім'я, знаходяться в межах сфери, на них можуть посилатися інші частини коду тощо. Вони є логічною сутністю. Компілятор вільний реалізовувати цю мовну конструкцію будь-яким способом, який їй заманеться, доки спостережувана поведінка є такою, що визначена мовним стандартом. Таким чином, змінну навіть не потрібно зберігати ніде, якщо компілятор може довести, що це не потрібно.

Місце пам'яті - це апаратне поняття . Вони означають місце у віртуальній / фізичній пам'яті. Кожне місце пам'яті має рівно одну фізичну адресу та будь-яку кількість віртуальних адрес, які можуть використовуватися для маніпулювання ним. Але завжди є точно один байт, який зберігається в кожному місці пам'яті.

Покажчики - це особливий вид цінностей . Скажіть, що щось є вказівником, це схоже на те, що говорити про щось типу double. Це означає, скільки бітів використовується для значення та як інтерпретуються ці біти, але це не означає, що це значення зберігається в змінній, а також не означає, що це значення зберігається в пам'яті.


Щоб навести приклад в C: Коли у мене є двовимірний масив int foo[6][7];і я отримую доступ до його елемента foo[1][2], тоді fooце змінна, яка містить масив. Коли fooвикористовується в цьому контексті, він перетворюється на вказівник на перший елемент масиву. Цей покажчик не зберігається в жодній змінній, а також не зберігається в пам'яті, його значення генерується лише в реєстрі процесора, використовується, а потім забувається. Так само вираз foo[1]у цьому контексті перетворюється на інший покажчик, який, знову ж таки, не є змінною, не зберігається в пам’яті, а обчислюється в процесорі, використовується і забувається. Три змінні поняття , місце пам'яті та вказівник - це справді три різні поняття.


До речі, я справді мав на увазі, що "в кожному місці пам'яті завжди зберігається точно один байт". Це було не так у кам'яну епоху обчислень близько п’ятдесяти років тому, але це стосується практично всього обладнання, яке використовується сьогодні. Щоразу, коли ви зберігаєте значення в пам'яті, що перевищує один байт, ви фактично використовуєте ряд послідовних пам'яті. Тобто (якщо припустити велике байтове порядок) число 0x01234567 зберігається в пам'яті як

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

(Маленькі ендіанські машини, такі як архітектура X86, зберігають байти у зворотному порядку.) Це справедливо і для покажчиків: вказівник на 64-бітній машині зберігається у восьми послідовних байтах, кожен з яких має свою адресу пам'яті. Ви не можете подивитися на комірку пам'яті і сказати: "О, це вказівник!" Ви завжди бачите байти лише при погляді на пам'ять .


Як комп'ютер дізнається, коли починається і закінчується група послідовних пам’яток?
прогрес

6
@progner Це не так. Він інтерпретує байти в пам'яті відповідно до отриманих інструкцій. Ці вказівки також зберігаються лише в послідовності самих байтів. Для процесора єдина відмінність між байтом, який містить інструкцію, байтом, який містить символ, і байтом, який містить деякі біти з плаваючою точкою, - це те, як йому було доручено використовувати цей байт. Якщо байт виймається тому, що лічильник програми вказує на нього, він використовується як інструкція. Якщо він отриманий через те, що інструкція говорить про завантаження його в регістр поплавця, він використовується як дані з плаваючою точкою.
cmaster

7
@progner Це було насправді ключовим нововведенням фон-Нейманської архітектури: зберігати як інструкції, так і дані в одній пам’яті, дозволяючи інструкціям змінювати дані, які згодом виконуються як інші інструкції. Це дозволило самостійно змінювати код, але воно також дозволяє ядру системи завантажувати якусь програму в пам'ять, а потім повідомити ЦП виконувати цю програму. До фон-Неймана такі комп’ютери, як машини Zuse, отримували свої вказівки через канал, повністю незалежний від даних, якими вони керували.
cmaster

5

Дозвольте зосередитися на вашому актуальному питанні - "хто прав?" при порівнянні цих двох тверджень:

  • Покажчик - це змінна, значення якої - адреса пам'яті іншої змінної
  • Вказівник - це місце пам'яті, значенням якого є адреса пам'яті іншого місця пам'яті.

Відповідь на це - жодна . Перший розповідає про "адресу пам'яті іншої змінної", але змінні не обов'язково мають адреси пам'яті, як уже пояснено в інших відповідях. Другий говорить: "покажчик - це місце пам'яті", але вказівник - це буквально просто число, яке може зберігатися в змінній, але, як і раніше, змінна не обов'язково має адресу пам'яті.

Деякі приклади для більш точних тверджень:

  • "Вказівник - це число, що представляє адресу пам'яті місця пам'яті", або

  • "Змінна вказівника - це змінна, значення якої - адреса пам'яті місця пам'яті."

  • "Адреса пам'яті може містити вказівник, що відображає адресу пам'яті місця пам'яті."

Зауважте, що іноді термін "покажчик" використовується як ярлик для "змінної вказівника", що нормально, доки це не призведе до плутанини.


Ви можете змінити "інший" на "а", тому що вказівник може вказувати на себе.
Пітер Б

@PieterB: nitty, nitty ;-) не впевнений, чи це насправді робить це зрозумілішим, оскільки я хотів лише змінити оригінальне формулювання на ступінь, дійсно необхідний, щоб зробити їх розумними. Але на жаль, я зробив правки.
Док Браун

Справедливо кажучи, якщо ви зрозуміли, що це "нитко", але вказівник буквально просто число ", також не вірно, насправді вказівник є ідентифікатором, що позначає число;) Або, принаймні, ми повинні знати мовні особливості, щоб потрапити в ці деталі.
Заїбіс

2
Покажчик - це значення (число вже занадто специфічне для деяких реалізацій), яке потенційно посилається на якийсь об'єкт. Потенційно тому, що є також нульові вказівники, дикі вказівники та звисаючі вказівники, хоча деякі (або навіть усі!) З них можуть бути виключені за допомогою використовуваної мови.
Дедуплікатор

2
@Deduplicator: ви праві, але я думаю, що ментальна модель вказівника як числа є досить хорошою для цілей цього питання. Тож давайте все буде просто.
Док Браун

5

Я, звичайно, не сказав, що вказівник - це місце пам'яті, яке містить адресу. Для одного я не знаю архітектури, де 0x23453міг би вміститися в один байт. :) Навіть якщо ви роздаєте байт / відмінність слова, у вас все ще виникає проблема, що кожне місце пам'яті містить адресу. Адреси - це просто числа, а вміст пам'яті - просто числа.

Я думаю, що фокус у тому, що "вказівник" описує людські наміри , а не якусь особливість архітектури. Це схоже на те, як "символ" або "рядок" не є конкретною річчю, яку ви можете бачити в пам'яті - це теж просто числа, але вони функціонують як рядки, тому що так вони поводяться. "Вказівник" означає лише значення, призначене для використання в якості адреси.

Чесно кажучи, якщо ваша мета - навчити певну мову (мета C?), Я не впевнений, що малювати класичну стрічку пам'яті навіть це корисно. Ви вже говорите білі брехні, показуючи набрані значення та значення, занадто великі для байти. Навчіть семантиці, а не механіці - ключове розуміння покажчиків полягає в тому, що вони забезпечують непрямість , що є масово корисним інструментом для розуміння.

Я думаю, що хорошим порівнянням може бути URL-адреса, яка вказує вам, де можна знайти деякі дані, але це не самі дані. Вислухай мене:

  • Вас рідко хвилює, що насправді є URL-адресою ; переважна більшість із них вивітрилася у зв’язках з іменами. Багато людей користуються Інтернетом, не знаючи, як саме URL-адреса відображається на сторінці; деякі люди повністю не звертають уваги на URL-адреси.

  • Не кожен рядок є URL-адресою або призначений для використання в якості URL-адреси.

  • Якщо ви спробуєте відвідати неправдиву URL-адресу або сторінку, яка існувала, але з тих пір була видалена, ви отримуєте помилку.

  • URL-адреса може вказувати на зображення, текст, деяку музику або будь-яку кількість інших окремих елементів - а також може вказувати на сторінку з різними речами, що містяться всередині. Дуже часто буває ціла купа сторінок з подібними макетами, але різними даними.

  • Якщо ви робите веб-сторінку і хочете посилатися на дані на якійсь іншій веб-сторінці, вам не потрібно копіювати і вставляти все це; ви можете просто зробити посилання на нього.

  • Будь-яка кількість інших сторінок може посилатися на ту саму URL-адресу.

  • Якщо у вас є колекція подібних сторінок, ви можете зробити індексну сторінку, яка містить перелік посилань на всі вони, або ви можете просто мати "наступне" посилання внизу сторінки 1, яке переходить на сторінку 2 тощо. Переваги та недоліки обох підходів відразу очевидні, особливо якщо врахувати, що потрібно зробити веб-майстру, щоб додати або видалити сторінки в різних місцях.

Ця аналогія робить його дуже ясно , що покажчики на , що дуже важливо для розуміння їх - в іншому випадку вони просто здаються довільними, складно, і безглуздо. Розуміти, як щось працює , набагато простіше, якщо ти вже розумієш, що це робить і чому це корисно. Якщо ви вже усвідомлювали, що вказівник - це чорна скринька, яка вказує вам, де щось інше, а потім ви дізнаєтесь про тонкощі моделі пам'яті, то подання покажчиків як адрес є досить очевидним. Крім того, викладання семантики поставить ваших учнів у набагато краще місце для розуміння та винайдення інших форм непрямості - що добре, коли більшість основних мов взагалі не мають покажчиків!


every memory location contains an address- Кожне місце пам'яті має адресу. Він не міститься ніде, за винятком, можливо, змінної вказівника.
Роберт Харві

@RobertHarvey кожне місце пам'яті (принаймні слово) містить число, яке можна тривіально інтерпретувати як адресу. справа в тому, що нічого в апаратному забезпеченні насправді не відрізняє адреси від не адреси
Eevee

2

Я знаю, що ви вже прийняли відповідь, і на це запитання вже є п'ять відповідей, але є момент, який вони не згадують, один, який, на мою думку, вас спричинив. Підручники CS часто намагаються бути агностичними щодо вибору мови програмування, що призводить до неявного припущення, що термінологія, що використовується для опису речей, є універсальною. Це не так.

У C оператор одинарного амперсанда називається оператором "address-of". Програмісти C не соромляться сказати, що вираз &xоцінюється за адресою змінної x. Звичайно, вони означають "адресу пам'яті, в якій зберігається значення змінної x", але ніхто не є таким педантичним у випадковій розмові. У C слово "покажчик" зазвичай посилається на тип даних змінної, яка має адресу пам'яті як її значення. Або еквівалентно тип даних значення. Але деякі люди використовуватимуть «покажчик» як саме значення.

У Java всі змінні типу об'єкта чи масиву ведуть себе так само, як і покажчики C (за винятком арифметики покажчика), але програмісти Java називають їх посиланнями, а не покажчиками.

C ++ вважає посилання та покажчики різними поняттями. Вони пов'язані, але не зовсім одне і те ж, тому програмістам на C ++ доводиться розрізняти розмову. У деяких контекстах "амперсанд" читається як "адреса", а в інших - "посилання на".

Покажчик - це змінна, значення якої - адреса пам'яті іншої змінної.

Ось так може описати програміст C, використовуючи "покажчик" у тому ж сенсі, що і "int". (Як і в "вказівник містить адресу пам'яті, а int - ціле число в певному діапазоні.")

Вказівник - це місце пам'яті, значенням якого є адреса пам'яті іншого місця пам'яті.

Це незвичайний спосіб сказати це, тому що це вимагає дуже вільного і неформального визначення поняття "є".

Чи безпечно сказати, що змінна - це те саме, що і місце пам'яті?

Ясніше було б сказати, що адреса пам'яті - це місце в пам'яті, де зберігається значення змінної. (Звичайно, не всі змінні зберігаються в пам'яті завдяки оптимізаціям компілятора, але будь-яка змінна, адреса якої взята, &xбуде.)


Як ми ведемо педантично: Адреса, за якою зберігається щось. Окрім адреси, яка нічого не може зберігати, часто речі зберігаються у кількох сусідніх місцях, лише один із яких (як правило, обраний за деяким послідовним правилом) адресований (і використовується лише одна з потенційно багатьох адрес).
Дедуплікатор

@Deduplicator Я, наприклад, не намагаюся бути педантичним.
Гаткін

Стандарт C навіть формально розрізняє змінні, які повинні суворо виконувати кроки абстрактної машини в кожній "точці послідовності" - задля безпеки потоку та певних операцій низького рівня на апаратному забезпеченні, нанесеному на пам'ять, - і тими, які не роблять " t, які можуть бути переміщені до реєстру або повністю оптимізовані.
Девіслор

@Davislor: Стандарт C використовує термін "об'єкт" у місцях, де в інших специфікаціях мови використовується "змінна", а також для опису інших речей, що не є змінними. Деякі дискусії можуть використовувати мовно-агностичний термін "змінна", але з будь-якої причини у Стандарту відсутній термін для розрізнення названих неперервних виділень (змінних) від інших видів об'єктів, таких як вкладені розподіли (члени структури / об'єднання) або неіменовані об'єкти. за перенаправленням покажчиків. Неофіційно "змінна" - це чудовий термін, але Стандарт не використовує його.
supercat

@supercat Це невірно. Стандарт C11 використовує термін "змінна" більше ста разів, з яких кілька десятків є іменниками, наприклад, "Одночасний доступ до змінної, ініціалізованої навіть за допомогою атомної операції, являє собою перегони даних".
Девіслор

1

Оператор Вказівник - це змінна, значення якої є адресою пам'яті іншої змінної спрощено. Але до того моменту, як читач зрозуміє, що таке саме місце в пам'яті, і чим він відрізняється від змінної, вони вже зрозуміють, що саме є вказівником, і тому більше не потрібно покладатися на це неточне пояснення.

Оператор Вказівник - це місце в пам'яті, значенням якого є адреса пам'яті іншого місця пам'яті . Значення вказівника не потрібно зберігати у пам'яті, і це дискусійно, якщо вказівник повинен вказувати на місце пам'яті, залежно від призначеного визначення "пам'яті".

Яка різниця між змінною та місцем пам'яті

Місце пам'яті - одне з декількох можливих місць, де можна зберігати дані. Ці дані можуть бути змінною або частиною змінної. Змінні - це спосіб маркування даних.


0

Ця відповідь зосереджена на C і C ++; Це здається підходящим, оскільки ваше питання стосується покажчиків, які є більш невід'ємною частиною C / C ++, ніж інші мови. Більшість цієї публікації стосуватиметься більшості скомпільованих мов без чіткого часу виконання (наприклад, Pascal чи Ada, але не як Java чи C #).

Надані добрі відповіді підкреслюють, що змінна - це мовна конструкція на більш абстрактному рівні, ніж фізична пам'ять. Хочеться підкреслити, що ця абстракція має певне обгрунтування та систему:

Абстракція головним чином полягає у використанні імені замість буквальної адреси.

Принципова ідея полягає в тому, що змінна - це названа ручка для введеного об'єкта; об'єкти в C / C ++ зазвичай знаходяться в пам'яті. Потім мови додають деякі приналежності, пов’язані з керуванням життям та обробкою даних для перетворень типів. Поняття змінних є більш абстрактним, ніж фізичні адреси, тому що нас насправді не цікавить числове значення адрес або точне розташування функцій у пам'яті. Ми просто називаємо їх і пізніше звертаємося до них по імені, а компілятор, компонувальник та система виконання дбають про стислі деталі.

І не робіть вигляд, що C / C ++ є агностиком пам’яті: зрештою, існує загальноприйнятний оператор адреси. Так, правда, ви не можете прийняти адресу змінної C у класі зберігання реєстру; але коли ти востаннє використовував? Це особливий виняток із загальної концепції, а не оптове відхилення аргументу. Загальне правило, навпаки, те, що прийняття адреси змінної насправді змушує компілятор дійсно створити об'єкт в пам'яті, навіть якщо це не зробить інакше (наприклад, з константами). Концепція "названої ручки" також є хорошою парадигмою для посилань на C ++: Посилання - це лише інша назва цього ж об'єкта.

Коли я писав вбудований асемблер за 68 к, було приємно бачити, як ви можете використовувати імена змінних як компенсації для адресних регістрів (а ви можете використовувати імена змінних, оголошених registerзамість імен реєстру голих металів!). Для компілятора змінна - це постійне зміщення адреси. Повторюю: Змінні називаються ручками, як правило, для об'єктів у пам'яті.


Покажчики є дуже базовою частиною C #, Java, JS та інших мов. Викликаючи їх по-різному, це не змінює, хоча це хороший піар.
Дедуплікатор

@Deduplicator :-) Good ol 'Tony ...
Пітер - Відновити Моніку

0

Здається, що питання спрямоване на популярну мову, сформовану шляхом доповнення стандарту C з додатковою гарантією "У випадках, коли деякі частини Стандарту або документація на імплементацію описують поведінку певної дії, а інша частина класифікує її як невизначену , колишня частина домінує. ", а також визначення поняття" змінна ", що відповідає використанню цього терміна в інших мовах.

У цій мові кожне місце пам’яті може розглядатися як пронумерована поштова скринька, яка завжди містить деяку кількість (зазвичай вісім) біт, кожен з яких може незалежно бути нулем або одиницею. Місце пам'яті, як правило, організоване в рядки з двох, чотирьох або восьми. а деякі операції обробляються в декількох послідовних місцях пам'яті одночасно. Залежно від машини, деякі операції, які виконуються на групах з двох, чотирьох або восьми місць пам’яті, можуть бути обмежені роботою над місцями в одному рядку. Крім того, хоча деякі машини можуть мати одну кімнату послідовно пронумерованих поштових скриньок, інші можуть мати кілька роз'єднаних груп пронумерованих поштових скриньок.

Змінна ідентифікує діапазон місць пам'яті, які пов'язані виключно з нею, і тип, який слід інтерпретувати в цих місцях пам'яті. Читання змінної призведе до інтерпретації бітів у відповідних місцях зберігання таким чином, що відповідає типу змінної, а запис змінної призведе до встановлення пов'язаних бітів таким чином, що відповідає її типу та значенню.

Адреса інкапсулює будь-яку інформацію, необхідну для ідентифікації поштової скриньки. Це може зберігатися як просте число або як якийсь груповий позначення разом із номером поштової скриньки в межах цієї групи.

Застосування &оператора до змінної дасть вказівник, який інкапсулює адресу та тип їх. Застосування унарного *або []оператора до вказівника призведе до інтерпретації або встановлення бітів поштових скриньок, що починаються з інкапсульованої адреси, таким чином, що відповідає типу інкапсульованого типу.


Це здається, ніби ви передумуєте питання.
Роберт Харві

0

Я запізнююсь на цю вечірку, але не можу втриматися, щоб вкласти свої 2 центи.

Яка різниця між значеннями, які зберігаються в цих місцях пам'яті?

Час 1

введіть тут опис зображення

Час 2

введіть тут опис зображення

Правильна відповідь: нічого. Всі вони є однаковими цінностями, представленими різними тлумаченнями їхнього значення.

Звідки я це знаю? Тому що я той, хто це придумав. Ви цього ще не знаєте.

Ви стикаєтесь з чимось я називаю проблемою поза смугою . Як правильно інтерпретувати значення цих значень, тут не зберігається. Ці знання зберігаються в іншому місці. Але коли ви представляєте ці значення на папері, ви вкладаєте цю інтерпретацію. Це означає, що ви додали інформацію, яка просто не існує в цих місцях пам'яті.

Наприклад, значення тут ідентичні, але ви знаєте, що це правда лише в тому випадку, коли ви правильні, коли ви припускаєте кодування символів ASCII / UTF-8 - це я отримав перше, а не EBCDIC . І ви також повинні припустити, що другий - це шістнадцяткові вирази числових значень, збережених у тих місцях пам'яті, які можуть бути всіма вказівниками на інші адреси, а не сказати посилання на рядки, які всі трапляються починаються з "0x". : P

Ніщо, що зберігається в цих місцях пам'яті, не говорить про те, що будь-яке з цих припущень є правильним. Ця інформація може зберігатися. Але вона зберігалася б в іншому місці.

Це проблема презентації . Ви взагалі не можете висловити будь-яке число, не погодившись із тим, як його подати. Ви можете спиратися на припущення, умовності та контекст, але якщо ви глибоко подряпаєте це, коли презентація не визначена чітко, єдина справді правильна відповідь - "недостатньо інформації".


Ще веселіше, коли однакова пам’ять використовується одночасно для різних постійних речей.
Дедуплікатор

@Deduplicator True. Це завжди змушує мене думати про переосмислений склад c ++ . Ті ж біти бачили по-іншому.
candied_orange

@Deduplicator або, подумайте про це, союз у c
candied_orange
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.