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

374
02 апреля 2017, 01:23

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

Answer 1

Хотел было докоментировать ответ 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<T> someList -- тебе нужно обязательно дописать ref List<T> someList, даже, не смотря на то, что это и так ссылочный тип и передавать ссылку на ссылочный тип, вроде как, безсмысленно. Но это имеет смысл, ведь ты можешь нечаянно обмануть другого программиста или же самого себя в будущем.

А во всем остальном я согласен с ответом andreycha и дополнением VladDа. То есть:

  • указатели С "статичны", а объект в дотнете может быть перемещен сборщиком мусора, т.е. ссылки изменяют свое значение.
  • И что ссылка в C# не бывает «висящей» или указывать в случайную область памяти, она всегда ссылается на валидный объект или равна null
Answer 2

Концептуально -- да. Они решают задачу указания на объект. Но есть различия в реализации.

Указатели содержат адрес. Ссылки -- это, по сути, абстракция, которая ничего не говорит о своем значении (хотя по факту, CLR в них тоже помещает адрес).

Cсылка в C# всегда ссылается на валидный объект или равна null, указатель же может указывать в случайную область памяти. (спасибо за комментарий @VladD)

Кроме того, указатели С "статичны", а объект в дотнете может быть перемещен сборщиком мусора, т.е. ссылки изменяют свое значение.

Из этого факта вытекает еще одно отличие: в случае с указателями возможно безопасно делать арифметику (например, обращаться к i-му элементу массива, имея указатель на массив и зная размер элемента), в случае со ссылками -- нет.

В C# также существуют указатели. Они эквивалентны указателям в С.

READ ALSO
Смена фона нескольких страниц в wpf

Смена фона нескольких страниц в wpf

Всем доброго времени сутокВопрос заключается в том что в одной из n-страниц есть кнопки с названием цвет, и мне необходимо что бы при нажатии...

286
Vk audio Api. Загрузка аудио на сервер c#

Vk audio Api. Загрузка аудио на сервер c#

Доброго времени суток, понадобилось мне загрузить аудио в вк, нашел апи https://vkcom/dev/audio

594
Необработанное исключение типа &ldquo;System.NullReferenceException&rdquo;

Необработанное исключение типа “System.NullReferenceException”

При компиляции вылазит ошибка:

328
Href asp.net mvc

Href asp.net mvc

Пытаюсь сделать ссылку по якорям

250