Почему мастер Си Деннис Ричи ввел указатели в Си? И почему другие языки программирования, такие как VB.NET, Java или C #, устранили их? Я нашел несколько пунктов в Google, и я тоже хочу выслушать ваши комментарии. Почему они исключают концепции указателей в современных языках?
Люди говорят, что C является основным языком, а указатели - это концепция, которая делает C мощным и выдающимся, а C все еще конкурирует с более современными языками. Тогда почему они устранили указатели на более современных языках?
Как вы думаете, знание указателей все еще важно для новых программистов? В наши дни люди используют VB.NET или Java, которые поддерживают более продвинутые функции, чем C (и не используют никаких указателей), и многие люди, как я вижу сейчас (мои друзья), выбирают эти языки, игнорируя C, поскольку они поддерживают расширенные функции. Я говорю им начинать с C. Они говорят, что изучать концепции указателей - пустая трата времени, когда вы делаете сложные вещи в VB.NET или Java, которые невозможны в C.
Как вы думаете?
Обновлено :
Комментарии, которые я прочитал в Google:
Более ранние компьютеры были слишком медленными и не оптимизированы.
Использование указателей позволяет получить прямой доступ к адресу, что экономит время, а не копирует его при вызове функций.
Безопасность значительно хуже при использовании указателей, и поэтому Java и C # не включают их.
Эти и еще кое-что я нашел. Мне все еще нужны некоторые ценные ответы. Это будет с благодарностью.
Ответы:
В те времена разработчики работали гораздо ближе к металлу. По сути, C был заменой сборки на более высоком уровне, который почти настолько близок к аппаратному обеспечению, насколько это возможно, поэтому естественно, что вам нужны указатели, чтобы быть эффективными в решении проблем кодирования. Тем не менее, указатели являются острыми инструментами, которые могут нанести большой ущерб при неосторожном использовании. Кроме того, прямое использование указателей открывает возможность для многих проблем безопасности, которые тогда не были проблемой (в 1970 году Интернет состоял из нескольких десятков машин в нескольких университетах, и его даже так не называли). ...), но с тех пор становится все более и более важным. Так что в настоящее время языки более высокого уровня сознательно разработаны, чтобы избежать необработанных указателей памяти.
Сказать, что «продвинутые вещи, выполненные в VB.Net или Java, не возможны в C», показывает очень ограниченную точку зрения, если не сказать больше :-)
Прежде всего, все эти языки (даже ассемблер) являются полными по Тьюрингу, поэтому теоретически все, что возможно на одном языке, возможно на всех. Подумайте только о том, что происходит, когда часть кода VB.Net или Java компилируется и выполняется: в конце концов, он преобразуется (или сопоставляется) в машинный код, потому что это единственное, что понимает машина. В скомпилированных языках, таких как C и C ++, вы фактически можете получить полный объем машинного кода, эквивалентный исходному исходному коду более высокого уровня, в виде одного или нескольких исполняемых файлов / библиотек. В языках на основе виртуальных машин более сложно (и может даже не быть возможным) получить полное эквивалентное представление машинного кода вашей программы, но, тем не менее, в конечном итоге оно находится где-то в глубоких нишах системы времени выполнения и JIT.
Теперь, конечно, это совсем другой вопрос, возможно ли какое-то решение на конкретном языке. Ни один здравомыслящий разработчик не начал бы писать веб-приложение в сборке :-) Но полезно иметь в виду, что большинство или все эти языки более высокого уровня построены на основе огромного количества кода времени выполнения и библиотеки классов, большой кусок который реализован на языке более низкого уровня, как правило, на C.
Итак, чтобы перейти к вопросу,
Концепция указателей - косвенность . Это очень важная концепция, и ИМХО каждый хороший программист должен понять ее на определенном уровне. Даже если кто-то работает исключительно с языками более высокого уровня, косвенные ссылки и ссылки по-прежнему важны. Неспособность понять это означает неспособность использовать целый класс очень мощных инструментов, серьезно ограничивающих способность решать проблемы в долгосрочной перспективе.
Так что мой ответ - да, если вы хотите стать действительно хорошим программистом, вы должны понимать и указатели (а также рекурсию - это другой типичный камень преткновения для начинающих разработчиков). Возможно, вам не нужно начинать с этого - я не думаю, что C является оптимальным в качестве первого языка в наши дни. Но в какой-то момент нужно ознакомиться с косвенностью. Без этого мы никогда не сможем понять, как на самом деле работают инструменты, библиотеки и интегрированные среды. И мастер, который не понимает, как работают его инструменты, очень ограничен. Справедливо, можно понять это и на языках программирования более высокого уровня. Одним из хороших лакмусовых тестов является правильная реализация двусвязного списка - если вы можете сделать это на своем любимом языке, вы можете утверждать, что понимаете косвенное обращение достаточно хорошо.
Но если бы не что-то еще, мы должны сделать это, чтобы научиться уважать старых программистов, которым удалось создать невероятные вещи, используя смехотворно простые инструменты, которые у них были (по сравнению с тем, что мы имеем сейчас). Мы все стоим на плечах гигантов, и нам полезно это признать, а не делать вид, что мы сами гиганты.
источник
Я думаю, что вы должны отличаться.
Java и другие языки более высокого уровня не удаляли указатели. Что они сделали, так это удалили арифметику простого указателя.
Фактически, Java все еще допускает защищенную и ограниченную арифметику указателей: доступ к массиву. В простом старом C доступ к массиву - это не что иное, как разыменование. Это другая нотация, синтаксический сахар, если хотите, чтобы четко сообщить, что вы делаете.
Тем не менее,
array[index]
эквивалентно*(array+index)
. Из-за этого это также эквивалентно тому,index[array]
что я полагаю, что некоторые компиляторы Си могут дать вам предупреждение, если вы сделаете это.Как следствие,
pointer[0]
эквивалентно*pointer
. Это просто потому, что «указатель на массив» является адресом первой записи массива, а адреса последующих элементов вычисляются путем добавления индекса.В Java арифметика простого указателя (ссылка и разыменование) больше не существует. Однако указатели существуют. Они называют их ссылками, но это не меняет того, что есть. И доступ к массиву все тот же: посмотрите на адрес, добавьте индекс и используйте эту ячейку памяти. Однако в Java он будет проверять, находится ли этот индекс в границах массива, который вы изначально разместили. Если нет, он выдаст исключение.
Преимущество подхода Java в том, что у вас нет кода, который просто слепо записывает произвольные байты в произвольные области памяти. Это повышает безопасность и безопасность, потому что если вы не сможете проверить переполнения буфера и тому подобное, среда выполнения сделает это за вас.
Недостатком этого является то, что он просто менее мощный. Программирование, безопасное для памяти, возможно на языке C. Невозможно извлечь выгоду из скорости и возможностей небезопасного программирования на Java.
На самом деле, нет ничего сложного в указателях или арифметике указателей. Они просто обычно объясняются запутанными способами, тогда как весь указатель - это указатель на один гигантский массив (пространство вашей памяти), все ссылки на значение дают вам указатель, где его найти, все, что делает разыменование, это поиск значение по данному индексу. (Это немного упрощено, поскольку не учитывается, что значения в памяти различаются по размеру, в зависимости от их типа. Но это скорее косвенная деталь, а не часть реальной концепции)
ИМХО, все в нашей работе должны это понимать, или они просто не в той области.
источник
back2dos
был прав с первого раза, так как(array + index)
уже учитывает размеры объектов (в C).array[index]
, и это*(array+index)
. Если вы хотите показать, как компилятор работает внутренне, вы можете явно рассказать о байтах или дать сборку.Концепция указателей важна в общем объеме знаний по компьютерному программированию. Понимание концепции полезно для программистов и программистов любого языка, даже если язык не поддерживает его напрямую.
Указатели используются в структурах данных (связанные списки) и в дизайне базы данных (внешний ключ).
Такие языки, как VB и C #, могут передавать данные посредством «ссылки» на методы, которые можно рассматривать как тип указателя.
Понимание того, где данные расположены в памяти (стек или куча), все еще важно для эффективности алгоритмов.
Изучение основ правильных основ важно на мой взгляд.
источник
std::sort
,std::partition
,std::find
И т.п. Они работают с указателями, и они работают с объектами , которые действуют как указатели (итераторы). И они работают над любой общей коллекцией; связанные списки, динамические массивы,deque
деревья, деревья или любые другие виды пользовательских коллекций. Вы не можете такого рода абстракции без указателей.Да, да, да, да и да !!!
Если вы не знаете основ, вы НИКОГДА не сможете решить действительно сложные, странные, сложные и сложные проблемы, которые вам встретятся.
И если вы действительно хорошо понимаете основы, вы НАМНОГО более конкурентоспособны на рынке труда.
Однажды я работал с парнем, который программировал 10 лет, и понятия не имел, как работают указатели. Я (намного младше) провел часы за доской, обучая его. Это открыло мне глаза. У него не было ИДЕИ о стольких элементарных вещах.
Знай столько, сколько сможешь.
источник
Да, понимание важно.
Несколько месяцев назад я программировал на C # и хотел сделать копию списка. Конечно, то, что я сделал, было
NewList = OldList;
и затем начало изменятьсяNewList
. Когда я попытался распечатать оба списка, они были одинаковыми, так как они былиNewList
просто указателем,OldList
а не копией, так что яOldList
все время менялся . Мне не потребовалось много времени, чтобы понять это, но некоторые из моих одноклассников не были такими быстрыми, и им пришлось объяснить, почему это происходит.Пример:
И, конечно же, результат такой:
Знание того, как их использовать, не так важно, но понимание их крайне важно!
источник
NewList
был просто указатель наOldList
» - если быть точным, обаNewList
иOldList
были просто указателями, ссылающимися на один и тот жеList
объект.b
больше не имеет ссылок на него и теперь является мусором.Указатель концепции! = Указатель арифметики! = Указатель синтаксиса
Первое имеет значение всегда, если вам нужно (и вам нужно) понимание глубокой / мелкой копии, передача по ссылке / передача по значению и т. Д. Два других значения имеют значение только в том случае, если ваш язык du jour позволяет вам их использовать.
источник
a=[1,2]; b=a; a.append(3)
обаa
иb
оба будут ссылаться на один и тот же объект,[1,2,3]
не зная вещи, как в C, на этотi
элемент массива можно ссылатьсяarr[i]
илиi[arr]
как на оба*(arr+i)
. Я предпочитаю, когда язык не позволяетi[arr]
использовать.Потому что указатели являются очень мощным механизмом, который можно использовать разными способами.
Потому что указатели являются очень опасным механизмом, который может быть использован разными способами.
Я думаю, что программисты должны узнать об указателях, но с образовательной точки зрения, было бы неразумно вводить их рано. Причина в том, что они используются для очень многих различных целей, и как новичок трудно сказать, почему вы используете указатель в определенных обстоятельствах.
Вот неполный список, для чего используются указатели:
new T
)struct T { T* next; /* ... */ };
)for (T* p = &a[0]; p != &a[0] + n; ++p) { ... }
)T* new_pointer = existing_pointer;
)T* pointer_to_base = pointer_to_derived;
)mutate(&object);
)if (p) { /* ... */ }
)Обратите внимание, что использование единого механизма для всех этих концепций демонстрирует как мощь, так и элегантность для опытного программиста, а также большой беспорядок для новичка в программировании.
источник
Почему? Вы можете написать огромную систему с дизайнером форм и генератором кода. Разве этого не достаточно? (Ирония)
И теперь серьезно, указатели не являются важной частью программирования во многих областях, но они позволяют людям понять, как работают внутренние компоненты. И если у нас не будет никого, кто понимает, как работают внутренние устройства, будет ситуация, когда SQL2020, Windows 15 и Linux 20.04 будут написаны на виртуальной машине с сборкой мусора, выполняющей более 30 уровней абстракции, с кодом, сгенерированным с помощью IDE, в JavaScript ,
Это определенно не то, что я хочу увидеть.
Так что да, они должны, безусловно!
источник
Ни Java, ни C # не исключили указатели, у них есть ссылки, которые почти одинаковы. Что было устранено, так это арифметика указателей, которая может быть опущена во вводном курсе.
Ни одно нетривиальное приложение не может быть сделано без концепции указателей или ссылок, поэтому стоит учить (без них динамическое распределение памяти невозможно).
Рассмотрим следующее в C ++ и Java, и я полагаю, что в C #
aClass *x = new aClass();
aClass x = new aClass();
это не сильно отличается: между указателями и ссылками нет большой разницы, верно?
Следует избегать арифметики с указателями, если в этом нет необходимости, и при программировании на высокоуровневых моделях, поэтому проблем не возникает.
источник
Профессиональный программист должен освоить указатели.
Люди, которые хотят знать программирование, должны узнать о его существовании и последствиях, но не обязательно использовать их.
Люди, которые хотят решать личные проблемы с помощью программирования (например, я, использующий множество скриптов Python), вполне могут их вообще игнорировать.
Ну, это мое мнение ...; о)
источник
Указатели на переменные адреса являются частным случаем более обобщенной концепции косвенности. Направленность используется в большинстве (всех?) Современных языков во многих конструкциях, таких как делегаты и обратные вызовы. Понимание концепции косвенного обращения позволяет вам знать, когда и как лучше всего использовать эти инструменты.
источник
Абсолютно ДА ! Каждый, кто программирует, должен понимать указатели и косвенность.
Указатели показывают, как осуществляется доступ к большому количеству данных на всех языках. Указатели - это аппаратная особенность всех микропроцессоров. Языки высокого уровня, такие как Java, VB & C #, по существу блокируют прямой доступ к указателям от пользователей языка со ссылками. Ссылки ссылаются на объекты через схему управления памятью языка (например, это может быть указатель с метаданными или просто число для таблицы памяти).
Понимание того, как работают указатели, является основополагающим для понимания того, как на самом деле работают компьютеры. Указатели также более гибкие и мощные, чем ссылки.
Например, причина, по которой массивы начинаются с нулевого индекса, заключается в том, что массивы фактически являются сокращением для арифметики указателей. Не зная о том, как работают указатели, многие начинающие программисты не совсем получают массивы.
Строка 2 в арифметике указателя будет:
Без понимания указателей невозможно понять управление памятью, стеком, кучей или даже массивами! Кроме того, нужно понимать указатели и разыменования, чтобы понять, как передаются функции и объекты.
TL: DR : Понимание указателей имеет фундаментальное значение для понимания к компьютерам на самом деле работает .
источник
Я думаю, что это сводится к тому, что необходимость иметь дело с указателями отпала, поскольку программисты меньше обращались с прямым оборудованием, на котором они работали. Например, выделение структуры данных связанного списка таким образом, чтобы они идеально подходили к последовательности 640-байтовых модулей памяти, которые имелось на специализированном оборудовании.
Работа с указателями вручную может быть подвержена ошибкам (приводя к утечкам памяти и используемому коду) и требует много времени для получения правильных результатов. Так что Java, C # и т. Д. Теперь все управляют вашей памятью и указателями для вас через свои виртуальные машины (ВМ). Это, возможно, менее эффективно, чем использование сырого C / C ++, хотя виртуальные машины постоянно совершенствуются.
C (и C ++) по-прежнему являются широко используемыми языками, особенно в области высокопроизводительных вычислений, игр и встроенного аппаратного обеспечения. Лично я благодарен за то, что узнал об указателях, поскольку переход к ссылкам на Java (концепция, аналогичная указателям) был очень простым, и я не растерялся, когда увидел свое первое NullPointerException (которое на самом деле должно называться NullReferenceException, но я отступаю) ,
Я бы посоветовал узнать о концепции указателей, так как они по-прежнему лежат в основе множества структур данных и т. Д. Затем перейдите к выбору языка, на котором вы любите работать, зная, что если появится что-то вроде NPE, вы знаете, что на самом деле происходит. ,
источник
Это объективная истина:
Некоторые языки поддерживают прямой доступ к памяти (указатели), некоторые нет. Есть веские причины для каждого случая.
Как здесь кто-то сказал, еще во времена C автоматическое управление памятью было не таким сложным, как сегодня. И люди все равно привыкли к этому. У хороших программистов тогда было гораздо более глубокое понимание компьютерных программ, чем у нашего поколения (мне 21 год). Они использовали перфокарты и дни ожидания в течение некоторого времени компиляции на мэйнфрейме. Они, вероятно, знали, почему каждый бит в их коде существовал.
Очевидное преимущество таких языков, как C, состоит в том, что они позволяют лучше контролировать вашу программу. Когда вам это действительно нужно , в эти дни? Только при создании инфраструктурных приложений, таких как программы для ОС и среды выполнения. Если вы хотите просто разработать хорошее, быстрое, надежное и надежное программное обеспечение, то автоматическое управление памятью чаще всего является вашим лучшим выбором.
Дело в том, что прямой доступ к памяти в основном использовался на протяжении истории разработки программного обеспечения. Люди создавали программы с утечкой памяти, которые на самом деле работали медленнее из-за избыточного выделения памяти (в С легко и просто расширить пространство виртуальной памяти процесса для каждого отдельного выделения).
В наши дни виртуальные машины / среды выполнения гораздо лучше справляются с распределением и освобождением памяти, чем 99% программистов. Кроме того, они дают вам дополнительную гибкость в том потоке, который требуется вашей программе, потому что вы (в основном) не заняты освобождением выделенной памяти в нужное время и в нужном месте.
Что касается знаний. Я думаю, это замечательно, что программисты знают, как реализуются среды, в которых они программируют. Не обязательно до мельчайших деталей, но большая картина.
Я думаю, что знать, как работают указатели (по крайней мере), интересно. То же самое, что знать, как реализуется полиморфизм. Откуда ваш процесс получает свою память и как. Это вещи, которые всегда интересовали меня лично. Я могу честно сказать, что они сделали меня лучшим программистом, но я не могу сказать, что они являются необходимостью в образовании для тех, кто хочет стать хорошим программистом. В любом случае, знание большего часто сделает вас лучше на работе.
Потому что даже если вы не знаете всех мелких деталей, тот, кто это сделает, сможет превратить то, что вы создали, во что-то, что просто лучше работает. И это часто не сложная работа, если у вас есть правильный, чистый и проверяемый дизайн (и это обычно большая часть работы).
Если бы я был интервьюером и хотел нанять кого-то для заявления на языке высокого уровня, это было бы тем, что меня больше всего интересовало бы.
Знания низкого уровня - это бонус. Это хорошо для отладки и иногда создания немного лучших решений. Это делает вас интересным человеком, профессионально. Это дает вам некоторое уважение на вашем рабочем месте.
Но в современном мире это не священное требование.
источник
Для большинства практических целей в языках ОО высокого уровня достаточно понимания ссылок, вам не нужно понимать, как эти языки реализуют ссылки в терминах указателей.
Есть гораздо более функциональные и современные мультипарадигмальные подходы, которые я бы оценил гораздо выше, чем умение делать причудливую арифметику указателей, например, написать 1000-ю оптимизированную функцию копирования строк, которая, вероятно, работает хуже, чем String.copy вашей библиотеки std.
Я бы посоветовал сначала изучить гораздо более разнообразные концепции более высокого уровня, а также изучать языки разных конструкций, чтобы расширить свой кругозор, прежде чем пытаться специализироваться на аппаратных средствах.
Я часто вижу совершенно неудачные попытки микрооптимизации веб-сервлета или подобного кода с 5% -ной выгодой, когда кэширование (запоминание), оптимизация SQL или просто настройка конфигурации веб-сервера могут дать 100% или более без особых усилий. В большинстве случаев возиться с указателями - преждевременная оптимизация .
источник
Определенно, нам нужно иметь основательную концепцию указателя, если вы действительно хотите быть хорошим программистом. Причиной концепции Pointer стал прямой доступ к вашим ценностям, который становится более эффективным и действенным с ограничениями по времени ...
Кроме того, сейчас, учитывая мобильные приложения, которые имеют очень ограниченную память, мы должны использовать ее очень осторожно, чтобы ее работа была очень быстрой с откликом пользователя ... Так что для этой цели нам нужна прямая ссылка на значение ...
Рассмотрим устройства Apple или язык Objective C, который полностью работает только с концепцией указателя. Все переменные, объявленные в Objective C, имеют указатель. Вам нужно пройти через вики Objective C
источник