КОРОТКИЙ РЕЗЮМЕ
(який я також поставлю вгорі):
(0) Мислення покажчиків як адрес часто є хорошим інструментом навчання і часто є реальною реалізацією для покажчиків на звичайні типи даних.
(1) Але в багатьох, можливо більшості, вказівники компіляторів на функції не є адресами, а є більшими за адресу (як правило, 2х, іноді більше), або насправді вказівники на структуру в пам'яті, ніж містять адреси функцій та інше постійний басейн.
(2) Покажчики на члени даних та покажчики методів часто навіть незнайоміші.
(3) Спадковий код x86 з проблемами вказівника FAR та NEAR
(4) Кілька прикладів, особливо IBM AS / 400, із захищеними "жировими покажчиками".
Я впевнений, що ви можете знайти більше.
ДЕТАЛІ:
UMMPPHHH !!!!! Багато відповідей поки що є досить типовими відповідями "програміст віні", але не компілятор weenie або апаратне weenie. Оскільки я претендую на апаратне віні і часто працюю з компіляторними вихідними, дозвольте мені кинути свої два центи:
На багатьох, напевно, більшості компіляторів С, вказівник на дані типу T
є, власне, адресою T
.
Чудово.
Але навіть на багатьох таких компіляторах певні вказівники НЕ є адресами. Ви можете це сказати, подивившись sizeof(ThePointer)
.
Наприклад, вказівники на функції іноді бувають набагато більшими, ніж звичайні адреси. Або вони можуть включати рівень непрямості. Ця статтянадає одне опис із процесором Intel Itanium, але я бачив інші. Зазвичай для виклику функції ви повинні знати не тільки адресу коду функції, а й адресу постійного пулу функції - область пам'яті, з якої константи завантажуються однією інструкцією щодо завантаження, а не компілятор, який повинен генерувати 64-бітова константа з декількох інструкцій Load Immediate, Shift та OR АБО. Отже, замість однієї 64-бітової адреси вам потрібно 2 64-бітні адреси. Деякі ABI (бінарні інтерфейси додатків) переміщують це як 128 біт, тоді як інші використовують рівень непрямості, при цьому вказівник функції фактично є адресою дескриптора функції, який містить лише 2 згадані фактичні адреси. Який краще? Залежить від вашої точки зору: продуктивність, розмір коду, і деякі проблеми сумісності - часто код передбачає, що покажчик може бути переданий на довгий або довгий, але може також припускати, що довгий довгий рівно 64 біт. Такий код може не відповідати стандартам, але, тим не менш, клієнти можуть захотіти, щоб він працював.
Багато хто з нас мають болісні спогади про стару сегментовану архітектуру Intel x86, з БЛИЗЬКИМИ Вказівниками та дальніми вказівниками. На щастя, вони вже майже вимерли, тому лише короткий підсумок: у 16-бітному реальному режимі фактична лінійна адреса була
LinearAddress = SegmentRegister[SegNum].base << 4 + Offset
Якщо в захищеному режимі це може бути
LinearAddress = SegmentRegister[SegNum].base + offset
при цьому отримана адреса перевіряється на обмеження, встановлене в сегменті. Деякі програми використовували не дуже стандартні декларації вказівників FAR та NEAR C / C ++, але багато хто просто сказав *T
--- але були компілятори компілятора та лінкера, так що, наприклад, вказівники коду можуть бути поблизу покажчиків, лише 32-бітове зміщення проти всього, що знаходиться в регістр CS (сегмент коду), тоді як покажчики даних можуть бути покажчиками FAR, вказуючи як 16-бітний номер сегмента, так і 32-бітове зміщення для значення 48 біт. Тепер обидві ці кількості, безумовно, пов'язані з адресою, але оскільки вони не однакового розміру, яка з них адреса? Більше того, сегменти також містили дозволи - лише для читання, читання, запису, виконувані файли - на додаток до матеріалів, що стосуються фактичної адреси.
Більш цікавий приклад - IMHO - це сім'я IBM AS / 400. Цей комп'ютер одним із перших застосував ОС на C ++. Покажчики на цій машині зазвичай були в 2 рази фактичним розміром адреси - наприклад, як ця презентаціяговорить, 128 бітових покажчиків, але фактична адреса становила 48-64 біт, і, знову ж таки, деяка додаткова інформація, що називається здатністю, яка надала дозволи, такі як читання, запис, а також обмеження для запобігання переповненню буфера. Так: ви можете це зробити сумісно з C / C ++ - і якби це було всюдисущим, китайська PLA та слов'янська мафія не втручалися б у так багато західних комп'ютерних систем. Але історично більшість програм C / C ++ нехтували безпекою для продуктивності. Найцікавіше, що сімейство AS400 дозволило операційній системі створити захищені покажчики, які могли б надаватися непривілейованому коду, але які непривілейований код не міг підробити чи підробити. Знову-таки, безпека і, хоча стандарти відповідають, набагато неохайний нестандартний код C / C ++ не працюватиме в такій захищеній системі. Знову ж таки, існують офіційні стандарти,
Тепер я вийду із своєї мильної панелі безпеки та згадаю деякі інші способи, коли вказівники (різних типів) часто насправді не адреси: Покажчики на члени даних, вказівники на методи функцій членів та статичні версії їх більше, ніж звичайна адреса. Як говориться в цій публікації :
Існує багато способів вирішення цього [проблеми, пов’язані з одиничним проти багаторазового наслідування та віртуальним успадкуванням]. Ось як компілятор Visual Studio вирішує обробляти це: вказівник на член-функцію класу, що перебуває у множині, насправді є структурою ". Вони продовжують говорити:" Лиття покажчика функції може змінити його розмір! ".
Як ви, напевно, здогадуєтесь з моєї понтифікації щодо (в) безпеки, я брав участь у проектах апаратного / програмного забезпечення C / C ++, де вказівник розглядався швидше як здатність, ніж необроблена адреса.
Я міг би продовжувати, але сподіваюся, що ви зрозумієте цю ідею.
КОРОТКИЙ РЕЗЮМЕ
(який я також поставлю вгорі):
(0) мислення покажчиків як адрес часто є хорошим інструментом навчання і часто є реальною реалізацією для покажчиків на звичайні типи даних.
(1) Але в багатьох, можливо більшості, вказівники компіляторів на функції не є адресами, а є більшими за адресу (як правило, 2X, іноді більше), або насправді вказівники на структуру в пам'яті, ніж містять адреси функції та інші речі постійний басейн.
(2) Покажчики на члени даних та покажчики методів часто навіть незнайоміші.
(3) Спадковий код x86 з проблемами вказівника FAR та NEAR
(4) Кілька прикладів, особливо IBM AS / 400, із захищеними "жировими покажчиками".
Я впевнений, що ви можете знайти більше.