В стандарте C89 я нашел следующий раздел:
3.2.2.1 Lvalues и обозначения функций
За исключением случаев, когда это операнд оператора sizeof, унарный и оператор, оператор ++, оператор-оператор или левый операнд. оператора или оператора присваивания, значение l, которое не имеет типа массива, преобразуется в значение, хранящееся в указанном объекте (и больше не является lvalue). Если lvalue имеет квалифицированный тип, значение имеет неквалифицированную версию типа lvalue; в противном случае значение имеет тип lvalue. Если lvalue имеет неполный тип и не имеет типа массива, поведение undefined.
Если я прочитал его правильно, он позволяет нам создать lvalue
и применять к нему некоторые операторы, которые компилируются и могут вызывать поведение undefined во время выполнения.
Проблема в том, что я не могу придумать пример "lvalue с неполным типом", который может передавать семантическую проверку компилятора и триггеры undefined behavior
.
Считайте, что lvalue
lvalue - это выражение (с типом объекта или неполным типом, отличным от void), который обозначает объект.
и что неполный тип
Типы разделяются на типы объектов (типы, описывающие объекты), типы функций (типы, описывающие функции) и неполные типы (типы, которые описывают объекты, но не имеют информации, необходимой для определения их размеров).
Ошибка программы, которую я пробовал:
struct i_am_incomplete;
int main(void)
{
struct i_am_incomplete *p;
*(p + 1);
return 0;
}
и получил следующую ошибку:
error: arithmetic on a pointer to an incomplete type 'struct i_am_incomplete'
*(p + 1);
~ ^
Кто-нибудь может подумать о примере? Пример "lvalue с неполным типом", который может передавать семантическую проверку компилятора и триггеры undefined behavior
.
UPDATE:
Как сказал @algrid в ответе, я неправильно понял undefined behavior
, который содержит compile error
в качестве опции.
Возможно, я раскалываю волосы, я все еще удивляюсь, что основная мотивация здесь предпочтительнее undefined behavior
over disallowing an lvalue to have an incomplete type
.