Понимание сборки gdb для разницы указателей [duplicate]

Вы используете объект, содержащий ссылку нулевого значения. Таким образом, он дает пустое исключение. В примере строковое значение равно null, и при проверке его длины произошло исключение.

Пример:

string value = null;
if (value.Length == 0) // <-- Causes exception
{
    Console.WriteLine(value); // <-- Never reached
}

Ошибка исключения:

Необработанное исключение:

System.NullReferenceException: ссылка на объект не установлена ​​в экземпляр объекта. в Program.Main ()

13
задан unwind 29 January 2010 в 12:06
поделиться

5 ответов

На самом деле это не определено, согласно стандарту. Арифметика указателя не гарантируется работать, если указатели не указывают на элемент в или только за ним один и тот же массив.

Соответствующий раздел стандарта - 6.5.6: 9 (n1362 draft of c1x, но это не изменилось с c99), который гласит:

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

Скорее всего, вы получите 250, если ваш тип данных int равен 4 байтам, но нет никакой гарантии. Неопределенное поведение (в отличие от поведения, определенного реализацией) означает именно это, неопределенное. Все может произойти, вплоть до полного уничтожения большой доли пространства-времени.

Курс переподготовки:

  • Определенное поведение - это то, что предусмотрено стандартом , Реализации должны делать это, чтобы быть совместимыми.
  • Поведение, определяемое реализацией, остается за реализацией, но должно четко документировать это поведение. Используйте это, если вы не слишком заботитесь о переносимости.
  • Неопределенное поведение означает, что все может случиться. Никогда не делай этого!
32
ответ дан paxdiablo 1 September 2018 в 00:39
поделиться
  • 1
    Это правильный ответ, однако я думаю, что каждый хочет верить, что ответ будет равно 1000 / sizeof (int). Ну что ж! – Alok Singhal 22 January 2010 в 23:55

Поскольку p указывает на int и поэтому q, q-p будет 1000.

-7
ответ дан Boolean 1 September 2018 в 00:39
поделиться
  • 1
    делится на sizeof (int) – Pascal Cuoq 22 January 2010 в 14:39
  • 2
    Извините, но это неправильно. – Randy Stegbauer 22 January 2010 в 14:44
  • 3
    @Pascal Почему нам нужно разделить его на sizeof (int)? – NLV 22 January 2010 в 14:45
  • 4
    Они - указатели, поэтому вы рискуете многого, делая это таким образом ... но да, целочисленная математика - целочисленная математика, делаете ли вы это правильно или нет ... – GalacticCowboy 22 January 2010 в 14:45
  • 5
    Оставаясь у других соображениями о бросках между 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 "

2
ответ дан Edan Maor 1 September 2018 в 00:39
поделиться

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 элементов.

8
ответ дан Richard Pennington 1 September 2018 в 00:39
поделиться
  • 1
    Это то, что я искал. Я не беспокоюсь о -1 для моего вопроса. Почему вы делите 1000 / sizeof (int)? – NLV 22 January 2010 в 14:40
  • 2
    Вам лучше указать «if sizeof (int) 4». Это потому, что sizeof (char) всегда 1. – paxdiablo 22 January 2010 в 14:47
  • 3
    @paxdiablo: Верно. Мозг замораживается. – Richard Pennington 22 January 2010 в 14:48

q-p должен возвращать количество шагов с шагом, которое вы должны сделать, чтобы перейти от p до q. Это 1000 / sizeof(int) и равно 250. Помните, что q++ действительно перейдет к следующему элементу типа int, а не к середине его, поэтому он должен добавить 4 к фактическому значению указателя. Отсюда и результат.

2
ответ дан vava 1 September 2018 в 00:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: