Взятие адреса условного выражения - PullRequest
4 голосов
/ 10 мая 2019

У меня есть следующий код:

struct S {
    int x;
};

#define X(a, s) ((struct S*)(a ? &s : 0))

int main(void)
{
    int a;
    struct S s;
    struct S *t;
    int *x;

    a = 3;
    s.x = 4;

    x = &(X(a, s)->x);
    t = &(X(a, s));
}

Когда я скомпилировал это, я получаю сообщение об ошибке в последней строке:

test.c: In function ‘main’:
test.c:18:9: error: lvalue required as unary ‘&’ operand
     t = &(X(a, s));
         ^

Почему это так "& (X (a, s) -> x) "допустимый код, а" & (X (a, s)) "нет?Оба включают возвращение адреса условного выражения.

1 Ответ

4 голосов
/ 10 мая 2019

In &(X(a, s)), & применяется к ((struct S*)(a, &s : 0)). Тип этого выражения struct S*, и это значение (значение указателя на struct S). & не может применяться к значению, которое не является lvalue. 1

In &(X(a, s)->x), & применяется к ((struct S*)(a, &s : 0))->x. Это выражение берет указатель на struct S и использует его для ссылки на член x, который является int. Это lvalue, потому что он обозначает объект int, который является членом x (C 2018 6.5.2.3 4 явно говорит, что результат -> является lvalue). Поскольку это lvalue, к нему можно применить &.

Сноска

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

...