Арифметика нулевого указателя

[Д0] == сравнивает опорное значение объектов, тогда как equals() метод присутствует в java.lang.String класса сравнивает содержимое String объекта (к другому объекту).

3
задан Root 17 January 2019 в 10:02
поделиться

2 ответа

Стандарт С не допускает этого.

6.5.6 Аддитивные операторы (выделение мое)

8 Когда выражение, имеющее целочисленный тип, добавляется или вычитается из указателя, результат имеет тип операнда указателя. Если операнд-указатель указывает на элемент объекта массива , и массив достаточно велик, результат указывает на смещение элемента от исходного элемента, так что различие индексов полученного и исходного массива элементы равны целочисленному выражению. Другими словами, если выражение P указывает на i-й элемент объекта массива, выражения (P) + N (эквивалентно, N + (P)) и (P) -N (где N имеет значение n) указывают соответственно i + n-му и in-му элементам массива, если они существуют. Кроме того, если выражение P указывает на последний элемент объекта массива, выражение (P) +1 указывает один за последним элементом объекта массива, а если выражение Q указывает на один последний элемент последнего элемента массива, выражение (Q) -1 указывает на последний элемент объекта массива. Если и операнд-указатель, и результат указывают на элементы одного и того же объекта массива или один после последнего элемента объекта массива, при оценке не должно быть переполнения; в противном случае поведение не определено . Если результат указывает на один последний элемент массива, он не должен использоваться в качестве операнда оцениваемого унарного оператора *.

Для целей вышеизложенного указатель на отдельный объект рассматривается как указывающий на массив из 1 элемента.

Теперь ((uint8_t*)0) не указывает на элемент объекта массива. Просто потому, что указатель, содержащий нулевое значение указателя, не указывает на какой-либо объект . Сказано в:

6.3.2.3 Указатели

3 Если константа нулевого указателя преобразуется в тип указателя, результирующий указатель, называемый нулевым указателем, гарантированно сравнивается с указателем на любой объект или функцию.

Так что вы не можете делать арифметику с ним. Предупреждение оправдано, потому что, как упоминается во втором выделенном предложении, мы имеем дело с неопределенным поведением.

Не обманывайтесь тем фактом, что макрос offsetof возможно реализован подобным образом. Стандартная библиотека не связана с ограничениями, накладываемыми на пользовательские программы. Это может использовать более глубокие знания. Но делать это в нашем коде не очень хорошо определено.

0
ответ дан StoryTeller 17 January 2019 в 10:02
поделиться

Небольшое разъяснение по этой теме.

Прежде всего, это неопределенное поведение в соответствии со стандартом C по причинам, указанным StoryTeller:

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

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

Однако , выполнение арифметических операций с нулевыми указателями для извлечения смещений не ново, реализация C макроса offsetof использует его:

#define offsetof(st, m) ((size_t)&(((st *)0)->m))

И делает такая же арифметическая мода на указатели также часто встречается:

int *end = (int *)0 + array_size;

Эта строка практически совпадает с записью:

int *end = (int *)(sizeof(int) * array_size);

Я считаю, что вычисление смещения определяется реализацией, как компилятор [115 ] «Мог» разыменовать такие указатели, чтобы получить фактическое смещение памяти, что, конечно, очень маловероятно, но все же возможно.

Также обратите внимание, что это предупреждение для арифметики нулевого указателя относится к Clang 6.0. GCC не запускает его даже с -fsanitize=undefined.

0
ответ дан Root 17 January 2019 в 10:02
поделиться
Другие вопросы по тегам:

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