На платформе, где NULL представлен как 0, компилятор когда-либо генерировал неожиданный код для NULL <= p - PullRequest
4 голосов
/ 14 августа 2011

В C99 равенство ==, кажется, никогда не бывает неопределенным.Он может выдать 1 случайно, если вы примените его к недействительным адресам (например, &x + 1 == &y может быть истинным случайно).Это не приводит к неопределенному поведению.Многие, но не все, недопустимые адреса не определены для вычисления / использования в соответствии со стандартом, так что в p == &x с p висящим указателем или в &x + 2 == &y недопустимый адрес вызывает неопределенное поведение, а не ==.

С другой стороны, >= и другие сравнения не определены, когда применяются к указателям, которые не указывают в пределах одного и того же объекта.Это включает в себя тестирование q >= NULL, где q является действительным указателем.Этот тест является предметом моего вопроса.

Я работаю над статическим анализатором низкоуровневого встроенного кода.Для этого вида кода нормально делать что-то, что не соответствует стандарту.Например, массив указателей в коде такого типа может быть инициализирован с помощью memset(...,0,...), хотя в стандарте не указывается, что NULL и 0 должны иметь одинаковое представление.Чтобы быть полезным, анализатор должен принять такие вещи и интерпретировать их так, как ожидает программист.Предупреждение, что программист будет восприниматься как ложное срабатывание.

Таким образом, анализатор уже предполагает, что NULL и 0 имеют одинаковое представление (вы должны проверить свой компилятор относительно анализатора, чтобы убедиться, что онисогласен с такого рода предположениями).Я заметил, что некоторые программы сравнивают действительные указатели с NULL с >= ( эта библиотека является примером).Это работает так, как задумано, если NULL представлено как 0, а сравнение указателей скомпилировано как сравнение целых чисел без знака.Я только хочу, чтобы анализатор предупредил об этом, если, возможно, из-за агрессивной оптимизации, он может быть скомпилирован в нечто отличное от того, что программист имел в виду на обычных платформах.Отсюда мой вопрос: есть ли какой-нибудь пример программы, не оценивающей q >= NULL как 1, на платформе, где NULL представлен как 0?

ПРИМЕЧАНИЕ: этот вопрос не об использовании 0в контексте указателя, чтобы получить нулевой указатель.Предположение о представлении NULL является реальным предположением, потому что в примере memset() нет преобразования.

1 Ответ

2 голосов
/ 14 августа 2011

Определенно есть указатели, что при их повторном толковании их как целое число со знаком размера указателя будет иметь отрицательный знак.

В частности, вся память ядра на Win32, и если вы используете «большой адрес с учетом», то даже 1 ГБпространства пользователя, поскольку вы получаете 3 ГБ пространства пользователя.

Я не знаю деталей арифметики указателя c, но я подозреваю, что в некоторых компиляторах они могут сравниваться как <0. </p>

...