Вы используете объект, содержащий ссылку нулевого значения. Таким образом, он дает пустое исключение. В примере строковое значение равно null, и при проверке его длины произошло исключение.
Пример:
string value = null;
if (value.Length == 0) // <-- Causes exception
{
Console.WriteLine(value); // <-- Never reached
}
Ошибка исключения:
Необработанное исключение:
System.NullReferenceException: ссылка на объект не установлена в экземпляр объекта. в Program.Main ()
blockquote>
На самом деле это не определено, согласно стандарту. Арифметика указателя не гарантируется работать, если указатели не указывают на элемент в или только за ним один и тот же массив.
Соответствующий раздел стандарта - 6.5.6: 9 (n1362 draft of c1x, но это не изменилось с c99), который гласит:
Когда два указателя вычитаются, оба должны указывать на элементы одного и того же объекта массива или один за последним элементом объекта массива ; результатом является разность индексов двух элементов массива.
blockquote>Скорее всего, вы получите 250, если ваш тип данных
int
равен 4 байтам, но нет никакой гарантии. Неопределенное поведение (в отличие от поведения, определенного реализацией) означает именно это, неопределенное. Все может произойти, вплоть до полного уничтожения большой доли пространства-времени.Курс переподготовки:
- Определенное поведение - это то, что предусмотрено стандартом , Реализации должны делать это, чтобы быть совместимыми.
- Поведение, определяемое реализацией, остается за реализацией, но должно четко документировать это поведение. Используйте это, если вы не слишком заботитесь о переносимости.
- Неопределенное поведение означает, что все может случиться. Никогда не делай этого!
Поскольку p указывает на int и поэтому q, q-p будет 1000.
int
и int*
, остается тот факт, что (int)(p+1)
равен ((int)p)+sizeof(int)
. Аналогично, когда вы вычитаете указатели, как в (p+1)-p
, вы получаете результат 1
. Но если вы вычтите после кастинга, как в ((int)(p+1)) - ((int)p)
, вы получите sizeof(int)
.
– Pascal Cuoq
22 January 2010 в 15:40
Ответ: qp будет 250, если вы на машине, где int
- 4 байта.
Расчет:
q - p = 1000 1000/4 (размер int) = 250
Идея:
Идея арифметики указателя заключается в том, что если у вас есть указатель int
на 1000 и указатель int
до 2000, и попросите разницу, вы не спрашиваете, что такое 2000-1000. Что вы спрашиваете, сколько int
можно установить между ними.
Это очень удобно для всех видов операций, например:
int *i = 100;
i++; // This is **not** 101, it is 104, cause you actually want the next place an int could fit in memory.
Это особенно полезно при работе с массивами. Массив ints (определенный int arr[10]
) в основном обрабатывается как указатель. Когда вы пишете arr[5]
, компилятор переводит его на *(arr + 5)
, т. Е. Добавляет 5 к указателю int
с именем arr
и получает значение по этому адресу.
Причина, по которой это работает , потому что arr + 5
не означает «добавить 5 к значению arr», это означает «добавить все, что является neceassary к значению arr, чтобы идти вперед 5 int
s» или, точнее, «добавить 5 * sizeof(int)
до значения arr "
q - p - 250.
2000 - 1000 = 1000
1000 / sizeof(int) = 250
арифметика указателя, если sizeof (int) - 4. Edit: OK, чтобы уточнить. В C, когда два указателя имеют один и тот же тип, тогда разница между ними определяется количеством вещей между указанным типом между ними. Например,
struct foo { int ar[1000]; } big[10];
char small[10];
struct foo *fs, *fe;
char *ss, *se;
fs = &big[0]; fe = &big[9];
ss = &small[0]; se = &small[9];
fe - fs == se - ss;
То есть разница между двумя указателями в этом случае - это количество элементов массива между ними. В этом случае это 0, 1, ... 8 или 9 элементов.
q-p
должен возвращать количество шагов с шагом, которое вы должны сделать, чтобы перейти от p
до q
. Это 1000 / sizeof(int)
и равно 250. Помните, что q++
действительно перейдет к следующему элементу типа int, а не к середине его, поэтому он должен добавить 4 к фактическому значению указателя. Отсюда и результат.