2

Working on a project that must run in Visual C++ and GCC

Before understanding that lvalue casting of the assignment operator in C is not allowed, I was writing code like this in VC++:

    typedef uint64_t QWORD;
    QWORD A = 0xdeadbeef, T = 0;

    (char)A = T;

Notice the (char)A = T disassembles to:

    000000013F7F3D8E  movzx       eax,byte ptr [T]  
    000000013F7F3D95  mov         byte ptr [A],al  

and everything was working fine (it seemed). Next, I ran this code using GCC on linux and it reported this error:

"error: lvalue required as left operand of assignment"

After searching many Stack Overflow articles, I found a solution that works in VC++ and GCC:

    *(char*)&A= T;

and also correctly disassembles to

    000000013F7F3D9B  movzx       eax,byte ptr [T]  
    000000013F7F3DA2  mov         byte ptr [A],al

But, why did VC++ permit me to cast the lvalue?

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
vengy
  • 1,548
  • 10
  • 18
  • 2
    VC++ has bugs and its own language extensions.:) – Vlad from Moscow Oct 29 '19 at 11:16
  • 3
    You've tagged this as both `C` and `C++` - which are you using? MSVC allows this (with a warning) when compiled as `C` but ***not*** when compiled as `C++`. – Adrian Mole Oct 29 '19 at 11:21
  • 1
    Whenever you feel the need to write a C-style cast in C++, take that as a sign that you're doing something wrong. – Some programmer dude Oct 29 '19 at 11:24
  • 1
    The Microsoft compilers contain a number of extensions to make C more like how they or their customers thought it should be. Many beginning programmers imagine that the way to express the concept of "treat variable X as if it were type Y, and assign Z to it" is to write `(Y)X = Z`. It's nonsensical if you know C, but it made enough sense to Microsoft that they implemented it -- and there must be enough code out there that depends on it by now that they've left the extension in their compilers to this day. (I also wonder why you would even *want* to treat X as if it had type Y, but anyway.) – Steve Summit Oct 29 '19 at 11:31
  • What actually happens with MSVC is that `deadbeef` is changed to `deadbe00` and I didn't know about this "behaviour". – Weather Vane Oct 29 '19 at 11:31
  • Oh...I do like (Y)X=Z (as a pretty novice C programmer) rather than this `*(Y*)&X=Z` ;) – vengy Oct 29 '19 at 11:38
  • I guess `*(char*)&A=T` could be written as `(char&)A=T` or `reinterpret_cast(A)=T` - but afaik, it's undefined behaviour in C++. – Ted Lyngmo Oct 29 '19 at 11:41
  • Should note too that the rvalue notation below works in M$ C and GCC: `typedef uint8_t BYTE;` `T = (BYTE)A;` – vengy Oct 29 '19 at 11:59

0 Answers0