Подтвердить что ты не робот

Is & * p valid C, учитывая, что p является указателем на неполный тип?

Является ли приведенный ниже пример действительной полной единицей перевода в C?

struct foo;

struct foo *bar(struct foo *j)
{
    return &*j;
}

struct foo является неполным типом, но я не могу найти явный запрет на разглашение неполного типа в стандарте C. В частности, в п. 6.5.3.2 говорится:

Унарный оператор & дает адрес своего операнда. Если операнд имеет тип типа '', результат имеет тип '' указатель на тип. Если операнд является результатом унарного оператора *, ни тот, который оператора или оператора &, и результат будет таким, как если бы оба они были опущены, за исключением того, что ограничения на операторы по-прежнему применяется, и результат не является значением l.

Тот факт, что результат не является значением lvalue, не является родным - возвращаемые значения не обязательно должны быть. Ограничения для оператора * просто:

Операнд унарного * оператора должен иметь тип указателя.

и оператора &:

Операнд унарного оператора & должен быть либо функцией обозначение, результат оператора [] или унарного *, или lvalue который обозначает объект, который не является битовым полем и не объявлен с register спецификатором класса хранения.

Оба из них тривиально удовлетворяются здесь, поэтому результат должен быть эквивалентен просто return j;.

Однако gcc 4.4.5 не компилирует этот код. Вместо этого он дает следующую ошибку:

y.c:5: error: dereferencing pointer to incomplete type

Является ли это дефектом в gcc?

4b9b3361

Ответ 1

Да, я думаю, что это ошибка. Даже lvalues ​​неполных типов, поэтому *j, кажется, разрешено в зависимости от контекста:

6.3.2.1... lvalue - это выражение с типом объекта или неполный тип, отличный от void

В основном это должно работать до тех пор, пока вы ничего не делаете с такой lvalue, которая должна знать о структуре struct. Поэтому, если вы не получаете доступ к объекту или не спрашиваете его размер, это законно.

Ответ 2

Да. Указатели на C обычно имеют одинаковый размер (на некоторых встроенных системах они могут быть разными). Это означает, что компилятор может генерировать правильный код ассемблера для этого, даже если тип "неизвестен".

Вы можете использовать этот подход, чтобы полностью скрыть внутреннюю структуру данных снаружи. Используйте typedef, чтобы объявить указатель на структуру и объявить структуру во внутренних файлах заголовка (т.е. Файлы, которые не являются частью вашего общедоступного API).

Причина, по которой жалуется gcc 4.4.5, заключается в следующем: если вы используете указатели на неполный тип вне реализации, он должен работать. Но код является частью реализации, и здесь вы, вероятно, хотите иметь полный тип.

Ответ 3

В стандарте C99 (ISO/IEC 9899: 1999) описывается поведение:

§6.5.3.2 Операторы адреса и косвенности

Унарный и оператор возвращает адрес своего операнда. Если операнд имеет тип типа '', результат имеет тип '' указатель на тип. Если операнд является результатом унарного * оператора, ни тот оператор, ни оператор и не оцениваются, и результат выглядит так, как если бы оба были опущены, за исключением того, что ограничения на операторы все еще применяются, и результат не является именующий.

Это означает, что &*j эквивалентно j.

Однако j должен быть указателем на объект, и он является только указателем на неполный тип, как указано в GCC 4.4.5.

§6.3.2.3 Указатели

Указатель на void может быть преобразован в указатель или из указателя на любой неполный или объект тип. Указатель на любой неполный или тип объекта может быть преобразован в указатель на void и обратно; результат сравнивается с исходным указателем.

Обратите внимание, что он различает тип объекта и неполный тип; это часто встречается в стандарте.

Итак, это замечание в вопросе неверно:

Оба из них тривиально выполняются здесь,

Переменная j не является указателем на объект; это указатель на неполный тип, который не является объектом.


§6.2.5 Типы

[...] Типы разделены на типы объектов (типы, которые полностью описывают объекты), типы функций (типы описывающие функции) и неполные типы (типы, описывающие объекты, но не имеющие информация, необходимая для определения их размеров).