Являются ли составные операторы lvalue (или rvalue) в C?

Когда я исследовал определение макроса container_of в ядре Linux, я увидел составной оператор как определение макроса,

#define container_of(ptr, type, member) ({                      \
    const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
    (type *)( (char *)__mptr - offsetof(type,member) );})

однако неясный вопрос, на мой взгляд, заключается в том, какое утверждение принимается во внимание как rvalue. По-видимому, результат последнего утверждения используется как rvalue, но почему?

(type *)( (char *)__mptr - offsetof(type,member) );

Например, является ли приведенный ниже пример кода допустимым в C?

int g_count = 0xFF;

#define GLOBAL_COUNT do {g_count;} while(0)

int main(int argc, char *argv[])
{
    int local;
    local = GLOBAL_COUNT;
    local = 0;
    GLOBAL_COUNT = local;
    return 0;
}

Каково правило присваивания переменных в составных операторах?


person albin    schedule 03.01.2013    source источник


Ответы (2)


({}) — это расширение GNU для C, называемое выражением-оператором:

http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html

В C составной оператор — это оператор, а оператор не может использоваться в выражении.

person ouah    schedule 03.01.2013

Вы видите выражение оператора, а не составной оператор. Выражение оператора — это расширение GCC, которого нет в стандартном языке C.

В GCC выражения операторов возвращают свои результаты "по значению", что означает, что их результаты являются rvalue. Собственно, это согласуется с общей «философией» языка C: в C практически любые манипуляции над объектами lvalue приводят к тому, что они быстро теряют свою lvalue-ность и превращаются в rvalue. (В этом отношении C практически противоположен C++. C++ пытается сохранить lvalue-ness как можно дольше.)

person AnT    schedule 03.01.2013