Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are compound statements lvalue (or rvalue) in C?

When I examined the definition of the container_of macro in Linux Kernel, I saw a compound statement as a macro definition,

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

however the unclear issue in my mind is which statement gets taken into account as rvalue. Apparently result of the last statement is used as rvalue, but why?

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

For instance, is the code example below legal in 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;
}

What is the assignment rule for variables in compound statements?

like image 206
albin Avatar asked Dec 15 '22 15:12

albin


2 Answers

({}) is a GNU extension to C called a statement expression:

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

In C a compound statement is a statement and a statement cannot be used in an expression.

like image 154
ouah Avatar answered Jan 06 '23 20:01

ouah


What you see is a statement expression, not a compound statement. Statement expression is a GCC extension that does not exist in standard C language.

In GCC statement expressions return their results "by value", meaning that their results are rvalues. This actually is in agreement with general "philosophy" of C language: in C virtually any manipulations over lvalue objects make them to quickly lose their lvalue-ness and turn into rvalues. (In this regard C is virtually opposite of C++. C++ attempts to preserve the lvalue-ness as long as possible.)

like image 20
AnT Avatar answered Jan 06 '23 20:01

AnT