Разница между приведением, используемым в составных литералах, и обработкой по указателю? - PullRequest
2 голосов
/ 09 марта 2010

Рассмотрим следующий код:

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 '&'

}

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

Ответы [ 3 ]

4 голосов
/ 09 марта 2010

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

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

4 голосов
/ 09 марта 2010

Это потому, что «приведение» в составном литерале вовсе не приведение - оно просто выглядит как единое целое.

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

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

++((char *){(char *)p});
&((char *){(char *)p});
1 голос
/ 09 марта 2010

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

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

Читать Глубокая статья доктора Даобса о составных литералах.

...