Casting a pointer does not produce an lvalue. Why?

2019-01-09 12:45发布

After posting one of my most controversial answers here, I dare to ask a few questions and eventually fill some gaps in my knowledge.

Why isn't an expression of the kind ((type_t *) x) considered a valid lvalue, assuming that x itself is a pointer and an lvalue, not just some expression?

I know many will say "the standard disallows it", but from a logical standpoint it seems reasonable. What is the reason that the standard disallows it? After all, any two pointers are of the same size and the pointer type is just a compile-time abstraction that indicates the appropriate offset that should be applied when doing pointer arithmetic.

8条回答
贪生不怕死
2楼-- · 2019-01-09 13:24

Note that if x is a pointer type, *(type_t **)&x is an lvalue. However, accessing it as such except perhaps in very restricted circumstances invokes undefined behavior due to aliasing violations. The only time it might be legal is if the pointer types are corresponding signed/unsigned or void/char pointer types, but even then I'm doubtful.

(type_t *)x is not an lvalue, because (T)x is never an lvalue, regardless of the type T or the expression x. (type_t *) is just a special case of (T).

查看更多
乱世女痞
3楼-- · 2019-01-09 13:27

From a top level, it would generally serve no purpose. Instead of '((type_t *) x) = ' one might as well go ahead and do 'x = ', assuming x is a pointer in your example. If one wishes to directly modify values pointed by the address 'x' but at the same time after interpreting it to be a pointer to a new data type then *((type_t **) &x) = is the way forward. Again ((type_t **) &x) = would serve no purpose, let alone the fact it is not a valid lvalue.

Also in cases of ((int *)x)++, where at least 'gcc' does not complain along the lines of 'lvalue' it could be reinterpreting it as 'x = (int *)x + 1'

查看更多
登录 后发表回答