Страницы

Поиск по вопросам

четверг, 28 ноября 2019 г.

Чем различаются указатели в Си от ссылок в C#?

#c_sharp #c


Верно ли, что указатели в Си аналогичны ссылочным типам в C#?
    


Ответы

Ответ 1



Концептуально -- да. Они решают задачу указания на объект. Но есть различия в реализации. Указатели содержат адрес. Ссылки -- это, по сути, абстракция, которая ничего не говорит о своем значении (хотя по факту, CLR в них тоже помещает адрес). Cсылка в C# всегда ссылается на валидный объект или равна null, указатель же может указывать в случайную область памяти. (спасибо за комментарий @VladD) Кроме того, указатели С "статичны", а объект в дотнете может быть перемещен сборщиком мусора, т.е. ссылки изменяют свое значение. Из этого факта вытекает еще одно отличие: в случае с указателями возможно безопасно делать арифметику (например, обращаться к i-му элементу массива, имея указатель на массив и зная размер элемента), в случае со ссылками -- нет. В C# также существуют указатели. Они эквивалентны указателям в С.

Ответ 2



Позвольте я на простом примере объясню слова andreycha: Указатели содержат адрес. Ссылки -- это, по сути, абстракция, которая ничего не говорит о своем значении Допустим, имеется человек по имени Василий Пупкин, проживающий по адресу Ленина, 1. Его адрес является указателем. А понятие "дом Васи" является ссылкой. Можно сказать: "Едем на вечеринку в доме Васи", без точного указания адреса. Если Василий теперь переедет на улицу Леннона, 2, то адрес изменится и, соответственно, должен изменится указатель. Меж тем ссылка "дом Васи" останется по-прежнему валидной.

Ответ 3



Хотел было докоментировать ответ andreycha, но потом подумал что лучше запостить отдельный ответ. Начнем с того что понятием указателя(pointer) в С/С++ является адрес обьекта в оперативной памяти и представляет собой следующий синтаксис: int x; int *y = &x; // От любой переменной можно взять адрес при помощи операции взятия адреса "&". Эта операция возвращает указатель int z = *y; // Указатель можно разыменовать при помощи операции разыменовывания "*". Это операция возвращает тот объект, на который указывает указатель то есть перед названием стоит звездочка. Так же есть ссылка (reference) int x; int &y = x; int z = y; Ссылки — это +- то же самое, что и указатели, но с другим синтаксисом и некоторыми другими важными отличиями. Они там работают вместе и дополняют друг друга: через указатель можно узнать значение по ссылке в С/С++. В C# есть так же указатели и ссылки. Синтаксис указателя это такая же звездочка и применяется точно так же как и в Си/Си++ (это считается небезопасным кодом и нужно в настройках проэкта поставить галочку "Allow unsafe code" и использовать модификатор метода unsafe). И так же возможна неявная передача ссылки с использованием ключевого слова ref, вместо &. Хотя ref в целом используется несколько по-другому в шарпе, чем & в С++ и в реализации, соответственно, отличается. пример использования ref в шарпе: public void SomeMethod(ref int a) { a = 5; //здесь а==5 как внутри метода так и извне } var a =1; SomeMethod(ref a); Я бы не сказал бы, что указатели/ссылки в Си являются аналогом ссылочного типа в C#. Появление понятия ссылочных типов -- это просто следствие выбранной реализации, но не аналог. Прямыми аналогами же являются лишь перечисленные выше способы задвать указатели/референсы. А бездумное использование ссылочных типов напрямую как аналог -- это плохая практика. Например, если ты знаешь что в методе будет изменятся переданный параметр List someList -- тебе нужно обязательно дописать ref List someList, даже, не смотря на то, что это и так ссылочный тип и передавать ссылку на ссылочный тип, вроде как, безсмысленно. Но это имеет смысл, ведь ты можешь нечаянно обмануть другого программиста или же самого себя в будущем. А во всем остальном я согласен с ответом andreycha и дополнением VladDа. То есть: указатели С "статичны", а объект в дотнете может быть перемещен сборщиком мусора, т.е. ссылки изменяют свое значение. И что ссылка в C# не бывает «висящей» или указывать в случайную область памяти, она всегда ссылается на валидный объект или равна null

Комментариев нет:

Отправить комментарий