Яка різниця між вказівником, який вказує на розташування 0x0, і покажчиком, встановленим на NULL?


12

Чи покажчик, що вказує на 0x0000, такий же, як вказівник встановлений на NULL? Якщо значення NULL визначено мовою C, то в яке місце воно фізично перекладається? Це те саме, що і 0x0000. Де я можу знайти більш детальну інформацію про ці поняття?


1
Про це вже запитували в переповнюванні стека - stackoverflow.com/questions/1296843/… . Я думаю, що це для нас є кордоном, але я готовий на даний момент надати користь сумніву.
ChrisF

Відповіді:


12

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

Константний покажчик NULL , так як відповідь Карлсона правильно стверджує, або вираз постійного цілого числа зі значенням 0 (простим 0є найбільш поширеним прикладом), або такого виразу приведення до void*(наприклад (void*)0).

NULLце макрос, визначений у <stddef.h>кількох інших стандартних заголовках, який розширюється до визначеної нульовою константою покажчика . Розширення, як правило, 0або ((void*)0)( або зовнішні дужки потрібні для задоволення інших мовних правил).

Таким чином, буквальний 0при використанні в контексті, який вимагає вираження типу вказівника, завжди оцінює значення a null pointer, тобто унікальне значення вказівника, яке вказує на жоден об'єкт. Це не означає нічого про представлення нульового покажчика . Нульові покажчики дуже часто представляються як всі біти-нулі, але вони можуть бути представлені як будь-що. Але навіть якщо нульовий покажчик представлений як 0xDEADBEEF, 0або (void*)0все ще є константою нульового вказівника .

Ця відповідь на питання про stackoverflow охоплює це добре.

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

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


1
Одним із моїх поглядів із дизайном та розвитком C є те, що цифра нуль продовжує використовуватись як непридатне подання нульового покажчика. Ще в перші дні мови (наприклад, до появи таких речей, як прототипи функцій) вказівники та цілі числа були досить взаємозамінними, що використовувати "0" для нульового вказівника було просто, і воно "просто працювало". Після того, як виникла необхідність розрізняти цілу кількість нуль і нульовий покажчик, однак, представлення "0" повинно було бути застарілим на користь ключового слова або послідовності оператора.
supercat

Чи означає це, що вказівник NULL може фактично вказувати на якесь місце, коли йому присвоюється NULL залежно від платформи? Константа нульового вказівника може бути синтаксичною конструкцією, але що саме відбувається, коли запускається код? Припустимо, ця синтаксична конструкція була складена на платформі GNU / Linux. Яке значення вказівника, коли ми присвоїмо йому NULL? Чим ця адреса відрізняється від будь-якої іншої адреси?
Арпіт

1
@Arpith: Призначення NULLабо будь-яка константа нульового вказівника об'єкту вказівника встановлює значення цього об'єкта нульовому покажчику . На машинному рівні це може вказувати на якийсь дійсний шматок пам'яті. Перенаправлення нульового покажчика має невизначене поведінку; доступ до шматка пам'яті за адресою 0x0000000- правильна поведінка, як і буквально все інше. Ця адреса відрізняється від будь-якої іншої адреси тим, що (a) порівнюється з рівним NULLта (b) порівнюється нерівним з будь-яким вказівником на об'єкт C. Нульовий покажчик - це довільне значення вказівника, яке використовується для вказівки, що воно не вказує ні на що.
Кіт Томпсон

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

7

Кожна платформа, яка там є, може вільно визначити NULL так, як їй заманеться.

Відповідно до стандарту C, якщо ви призначите нуль покажчику, він буде перетворений на значення NULL (для цієї платформи.) Однак якщо ви візьмете покажчик NULL і киньте його до int, немає гарантій, що ви отримаєте нуль на кожній платформі там. Справа в тому, що на більшості платформ він буде нульовим.

Інформація про те , що матеріал , який Ви можете знайти в специфікації мови C . Одне джерело, на яке я не можу покластися, це: http://www.winapi.co.kr/pds/doc/ISO-C-FDIS.1999-04.pdf


2
Якщо вони вирішать відійти від стандарту, вони можуть переосмислитись NULL pointer constant. Наскільки я знаю, там немає компіляторів, які б це робили.
Карлсон

Чи є там якийсь компілятор, який не реалізує NULL як 0? І чи NULL гарантовано оцінює значення false?
ugoren

NULL гарантовано оцінює значення false як стандарт. Я не знаю, чи є якийсь компілятор (платформа, насправді), який не реалізує NULL як 0, і я в цьому серйозно сумніваюся, але стандарт не забороняє його, тому хто знає.
Майк Накіс

Існує плутанина між представленням в пам'яті абстрактної "константи нульових покажчиків" (як згадується в специфікації), яка може бути, як виробник платформи бажає, і визначенням NULLмакросу, який повинен розширюватися на 0C ++ і або 0або (void *)0в C, тому що це справжня "нульова константа покажчика".
Ян Худек

Хоча NULL теоретично може бути визначений як будь-що, проте стандарт має гарантію, що int-константа зі значенням 0, введеним у покажчик, призведе до нульового покажчика (ISO 9899: 1999 6.3.2.3/3). Макрос NULL stddef.h повинен бути нульовим покажчиком (7.17 / 3), тому було б дуже обтяжливим для компілятора не застосовувати NULL як 0 або (void *) 0.

1

Він визначений мовою С, оскільки немає жодної незмінної адреси машини, до якої він прирівнюється. Якби це було, нам не потрібна була б абстракція від нього! Навіть незважаючи на те, що на більшості платформ NULL з часом може бути реалізований як 0 певного типу чи іншого, просто неправильно вважати, що це так універсально, якщо ви взагалі дбаєте про портативність.


Ось які стандарти є для open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
Карлсон

0

Відповідно до розділу " Стандартний документ C " 6.3.2.3:

Ціле постійне вираження зі значенням 0, або такий вираз, переданий типу void *, називається константою нульового покажчика.55) Якщо константа нульового покажчика перетворена в тип вказівника, отриманий вказівник, який називається нульовим покажчиком, є гарантовано порівняти нерівне вказівник з будь-яким об’єктом чи функцією.

Поки що я не бачив компілятора, який відірвався від цього.


@ PéterTörök Ти маєш рацію, це типо. :)
Карлсон

1
Так, але зауважте, що він нічого не говорить про вказівник, який фактично має числове значення 0. Він може не робити, хоча на більшості платформ це і є.
Ян Худек
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.