Когда я читал статью с описанием различий в ОО и функциональном программировании, я наткнулся на указатели функций. Прошло много времени с тех пор, как я получил степень в области компьютерных наук (2003), и поэтому я искал указатели, чтобы освежить свою память.
Указатели - это переменные, содержащие ссылку на адрес памяти. Можно считать, что они указывают на данные, содержащиеся в этом адресе памяти, если такие данные существуют. Или, как в случае с данной статьей, они могут указывать точку входа в раздел кода и могут использоваться для вызова этого кода.
Почему это отличается от переменной? Переменные являются символическими именами для адресов памяти, и компиляторы заменят имя на фактический адрес. Это означает, что переменные содержат ссылки на ячейки памяти и могут рассматриваться как указывающие на данные по этому адресу, если такие данные существуют.
Если разница в поведении (возможно, указатель не может быть переназначен во время выполнения или ему может быть назначено только символическое имя переменной, а не любое другое значение), не означает ли это, что это просто переменная определенного типа, типа указателя? Точно так же переменная, объявленная как целочисленная, ограничена компиляцией в том, для чего она может использоваться.
Что мне здесь не хватает?
источник
Ответы:
Ваш вопрос интересен по нескольким причинам, поскольку требует тщательного разграничения нескольких вопросов. Но ваше видение кажется мне по существу правильным. Я не читал вашу ссылку до того, как написал большую часть этого ответа, чтобы избежать искажения моего ответа.
Во-первых, ваше утверждение
Variables are symbolic names for memory addresses
, оно почти правильное, но путает концепцию и ее обычную реализацию. На самом деле переменная - это просто контейнер, который может содержать значение, которое можно изменить. Обычно этот контейнер реализуется на компьютере как блок пространства памяти, характеризуемый и адресом, и размером, поскольку переменные могут содержать объект, который требует представления с большей или меньшей информацией.Но я рассмотрю в основном более абстрактную точку зрения на семантику языков, независимо от методов реализации.
Так что переменные - это просто контейнеры с абстрактной точки зрения. Такой контейнер не должен иметь имени. Тем не менее, языки часто имеют переменные, которые именуются путем привязки к нему идентификатора, поэтому использование переменной может быть выражено идентификатором. Переменная может на самом деле иметь несколько идентификаторов через различные механизмы псевдонимов. Переменная также может быть частью более крупной переменной: примером является ячейка переменной массива, имя которой можно назвать, указав переменную массива и индекс ячейки, но также можно связать с идентификаторами с помощью псевдонимов.
Я намеренно использую слово « контейнер» , которое несколько нейтрально, чтобы не вызывать другие слова, которые могут быть семантически загружены технически. Это на самом деле близко к концепции ссылки, описанной в wilipedia , которая часто путается с адресом памяти. Сам указатель слова часто понимается как адрес памяти, но я не думаю, что это имеет смысл при рассмотрении большинства языков высокого уровня и, вероятно, неуместно в документе для обсуждения, на который вы ссылаетесь (хотя адреса могут использоваться), так как это неуместно ссылаясь на конкретную реализацию. Тем не менее, он подходит для такого языка, как C, который должен быть намного ближе к концепциям реализации и архитектуре машины.
На самом деле, если вы посмотрите на переменные или значения на уровне реализации, может быть несколько сложных систем косвенного обращения, «указателей машинного уровня», но которые (и должны быть) невидимы для пользователя, так что абстрактная точка зрения Я развиваюсь может быть действительно. Для большинства языков программирования пользователю не нужно беспокоиться или даже знать о реализации, поскольку реализация может сильно варьироваться для данного языка. Это может быть неверно для некоторых языков, таких как C, которые преднамеренно близки к архитектуре машины, в качестве расширенной замены языков ассемблера, которые почти напрямую связаны с явным двоичным кодированием, но слишком низки для удобного использования в большинстве ситуации.
Что должен знать пользователь языка, а иногда и меньше, это то, что представляют собой значения и связанные операции, где они могут содержаться, как они могут быть связаны с именами, как работает система именования, как новые виды ценностей и т. д.
Итак, еще одна важная концепция - идентификаторы и наименования. Присвоение имени сущности (значению) можно сделать, связав идентификатор со значением (обычно в объявлении). Но значение также можно получить, применяя операции к другим именованным значениям. Имена могут быть использованы повторно, и существуют правила (правила области видимости) для определения того, что связано с данным идентификатором, в соответствии с контекстом использования. Существуют также специальные имена, называемые литералами, для именования значений некоторых доменов, таких как целые числа (например, ) или логические (например, истина).612 ).
Ассоциация неизменного значения с идентификатором обычно называется константой. Литералы в этом смысле постоянны.
«Контейнеры значений» также могут рассматриваться как значения, и их связь с идентификатором является переменной в обычном «наивном» смысле, который вы использовали. Таким образом, вы можете сказать, что переменная является «контейнерной константой».
Теперь вы можете задаться вопросом, в чем разница между связыванием идентификатора со значением (объявлением константы) или присвоением значения переменной, то есть сохранением значения в контейнере, определенном как константа контейнера. По сути, объявление может рассматриваться как операция, которая определяет нотацию, которая связывает идентификатор, который является синтаксическим объектом, с некоторым значением, которое является семантическим объектом. Назначение - это чисто семантическая операция, которая изменяет состояние, то есть изменяет значение контейнера. В некотором смысле объявление является мета-концепцией без семантического эффекта, за исключением предоставления механизма именования (то есть синтаксического) для семантических объектов.
Фактически, присваивания являются семантическими операциями, которые происходят динамически, когда программа выполняется, в то время как объявления имеют более синтаксическую природу и обычно должны интерпретироваться в тексте программы, независимо от выполнения. Вот почему статическая область видимости (то есть текстовая область видимости) обычно является естественным способом понять значение идентификаторов.
После всего этого я могу сказать, что значение указателя - это просто другое имя для контейнера, а переменная-указатель - это переменная контейнера, то есть контейнер (константа), который может содержать другой контейнер (с возможными ограничениями на содержащую игру, налагаемыми некоторыми система типов).
Что касается кода, вы заявляете
[pointers] might indicate the entry point to a section of code and can be used to call that code
, На самом деле это не совсем так. Часть кода часто бессмысленна сама по себе (с точки зрения высокого уровня или реализации). С точки зрения высокого уровня, код обычно содержит идентификаторы, и вы должны интерпретировать эти идентификаторы в статическом контексте, в котором они были объявлены. Но на самом деле существует возможное дублирование одного и того же статического контекста, в основном из-за рекурсии, которая является динамическим (во время выполнения) явлением, и код может быть выполнен только в соответствующем динамическом экземпляре статического контекста. Это немного сложно, но следствием этого является то, что правильной концепцией является замыкание, связывающее фрагмент кода и среду, в которой идентификаторы должны интерпретироваться. Замыкание - это правильная семантическая концепция, т. Е. Правильно определяемая семантическая ценность. Тогда вы можете иметь константы закрытия, переменные закрытия,Функция - это замыкание, обычно с некоторыми параметрами для определения или инициализации некоторых своих сущностей (констант и переменных).
Я пропускаю много вариантов использования этих механизмов.
Замыкания могут использоваться для определения ОО-структур на императивных или функциональных языках. На самом деле, ранняя работа над ОО-стилем (вероятно, до названия) была проделана именно так.
Бумага, на которую вы ссылаетесь, которую я быстро просмотрел, кажется интересной, написанной компетентным человеком, но, возможно, не легкой для чтения, если у вас нет значительного опыта работы с различными языками и их базовыми вычислительными моделями.
Но помните: многие вещи находятся в глазах смотрящего, пока он сохраняет последовательный взгляд. Точки зрения могут отличаться.
Отвечает ли это на ваш вопрос?
PS: это длинный ответ. Если вы считаете какую-то его часть неадекватной, пожалуйста, уточните, о чем она. Спасибо.
источник
Различие по определению и применению, указатель - это специализированная переменная для хранения адреса в памяти другой переменной; в терминах ООП указатель, вероятно, будет считаться наследующим его поведение от общего класса, называемого переменной.
источник