#c# #.net #arrays #pointers
#c# #.net #массивы #указатели
Вопрос:
При использовании указателя на массив я всегда обращался к элементам с помощью индексатора, такого как, myPtr[i] = stuff
; однако недавно я BitConverter
просматривал реализацию и обнаружил, что доступ к элементам осуществлялся с помощью, *(myPtr i) = stuff
.
Что мне показалось довольно странным, поскольку оба метода (насколько я знаю) делают одно и то же, то есть возвращают адрес myPtr i
, за исключением (на мой взгляд) метода индексатора, который выглядит намного более читаемым.
Итак, почему Microsoft решила увеличивать указатели так, как они это делали, в чем разница между этими двумя методами (есть ли преимущества в производительности)?
Комментарии:
1. Они генерируют один и тот же IL. Это просто вопрос стиля.
2.
ToBoolean
Метод отличный. Комментарии не соответствуют коду, и он имеет отличныйx == 0 ? false : true
шаблон вместо простогоx != 0
.
Ответ №1:
Как вы заявили, они делают то же самое.
Фактически, при доступе к an int*
оба ptr[i]
*(ptr i)
синтаксиса и будут пропускать проверку границ и указывать на некоторую память за пределами границ массива, если i
она больше длины массива.
Я почти уверен, что C #, как и C , унаследовал индексированный доступ к указателю массива, используя *(ptr index)
синтаксис из C. Я почти уверен, что это единственная причина, по которой доступны оба синтаксиса.
Комментарии:
1. Так
myPrt[i]
это просто синтаксический сахар? Никаких других различий, кроме этого?2. @Sam Да, другой разницы быть не должно.
3. @dcastro Насколько я помню, использование индексатора может дать вам
IndexOutOfRangeException
, в то время*(ptr index)
как просто укажет вам на некоторую память за пределами массива.4. @AndreySarafanov Использование индексатора даст вам IOR, например, если вы обращаетесь к массиву int. Если вы обращаетесь к an
int*
, то оба[index]
*(ptr index)
синтаксиса и будут указывать на некоторую память вне массива. Оба синтаксиса будут пропускать границы -проверьте.5. @dcastro Спасибо, мой плохой, должен был более внимательно прочитать вопрос.
Ответ №2:
Из спецификации языка CSharp (18.5.3):
Доступ к элементу указателя вида P[E] вычисляется точно как *(P E). (…) Оператор доступа к элементу указателя не проверяет наличие ошибок, выходящих за пределы, и поведение при доступе к элементу, выходящему за пределы, не определено. Это то же самое, что C и C .
Различий нет.
Ответ №3:
Чтобы прояснить разницу между []
оператором массива и указателем (что обсуждалось в ответе dcastro), вы можете проверить вывод приведенного ниже кода.
unsafe {
int[] arr = new[] { 1, 2 };
fixed(int* ptr = arr) {
for(int i = 0; i < arr.Length 1; i ) {
try { System.Console.WriteLine(*(ptr i)); } catch(Exception e) { System.Console.WriteLine(e.Message); }
try { System.Console.WriteLine(ptr[i]); } catch (Exception e) { System.Console.WriteLine(e.Message); }
try { System.Console.WriteLine(arr[i]); } catch (Exception e) { System.Console.WriteLine(e.Message); }
}
}
}
Вывод
1
1
1
2
2
2
0
0
Index was outside the bounds of the array.