2010-03-09 1 views
2

Рассмотрим следующий код:Разница между литой, используемой в составных литералах, и это делается по переменной указателя?

int main() 
{ 
    int *p; 

    ++((int){5}); //compile without err/warning 
    &((int){5});  //compile without err/warning 

    ++((char *)p); //Compile-time err: invalid lvalue in increment 
    &((char *)p); //Compile-time err: invalid lvalue in unary '&' 

} 

Почему Составные литералы не генерировать ошибки здесь?

ответ

4

Это потому, что «литье» в составном литеральном произведении вообще не является произведением - оно просто похоже на одно.

Комбинированный литерал (который является полной конструкцией (int){5}) создает значение lvalue. Однако оператор трансляции создает только rvalue, как и большинство других операторов.

Этот пример будет разрешено (но бесполезно, так же, как ваши int примеры):

++((char *){(char *)p}); 
&((char *){(char *)p}); 
4

Соединение буквальным не имеет отливать в нем. Часть ваших составных литералов не является литой. Это всего лишь часть составного литерала. Итак, вопрос в этом случае заключается в том, является ли составной литерал объектом, значением lvalue. Ответ - да, составной литерал - это значение lvalue. По этой причине вы можете применить к нему любые операторы, для которых требуется значение lvalue (например, ++ или &).

Вторая часть вашего примера содержит слепки. Результат литья всегда имеет значение r. Вы не можете использовать ++ и & с rvalues.

1

«слепок» в соединении буквального на самом деле не литой, а именно тип соединения буквального.
Итак, (int){5} действительно больше похож на анонимный int, следовательно, действительный lvalue, который может быть использован в любом месте объекта одного и того же типа (int в данном случае) могут быть использованы.

Принимая во внимание, (char *)p на самом деле литая (rvalue), поэтому он не может быть увеличен ++ или ссылок &.

Прочитано Dr.Doobs's in-depth article о составных литералах.

Смежные вопросы