This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Error C213

Hello,

In trying to compile the C code with the C51
compiler [Keil µvision2], I received error c213 "left side of asn-op not an lvalue" -
" the address of a changeable object is required at the right side of the
assignment operator". But i don't know where is/are problems...

Code:
#include <Chipcon\srf04\regssrf04.h>
#include <Chipcon\srf04\halsrf04.h>
#include <Chipcon\srf04\ebsrf04.h>
#include <ctype.h>

#define TX_entree 0x80 //P0.4
#define RI0 0x98

BYTE idata txBuffer[8];
BYTE idata buffer[8];
int i = 0;
int taille_tab;

void main () {

#ifdef STAND_ALONE

CLOCK_INIT();
IO_PORT_INIT();

#endif

ebLcdInit();
ebLcdUpdate("Emission test v0.1", NULL);
halWait(3000);
ebLcdUpdate("Initialisation", NULL);
halWait(2000);
halUartSetup(UART_BAUDRATE_115200, DEFAULT_MODE);

SPI_INIT(SCLK_6_MHZ);
POWER_UP_RESET_CCxxx0(); FIRST ERROR
UART_RX_ENABLE();
ebLcdUpdate("Reception et stockage des données en cours", NULL);
halWait(3000);


if(RI0 == 1){
//stockage des données
taille_tab = sizeof(buffer);
for (i = 1; i < taille_tab; i++) {
UART_WAIT_AND_RECEIVE(buffer[i]); SECOND ERROR IF I COMMENT THE FIRST
}
}
ebLcdUpdate("Emission des données en cours", NULL);
halWait(2000);
SPI_ENABLE();
halRfSendPacket(buffer, sizeof(buffer));
ebLcdUpdate("Fin", NULL);
halWait(2000);
}

Any help or comments appreciated. I'm workin' on the CC2500DK, it's an tranceiver HF and many fonctions has already created by the constructor.

Thanks

John

Parents
  • The issue is "making the macro look like a function call" which is a wonderful way to obfusciate the code.

    You've let yourself get confused. This is not about adding obfuscation, but about keeping it under control.

    The goal of the do..while(0) trick is not to make the macro call look like a function call --- the mere fact of it being a function-like macro with a parameter list already achieves that.

    The actual goal is to make the macro invocation not just look like a function call (including an argument list), but also actually act like one, in all possible contexts. The tricky one being

    if (foo)
      MYMACRO(bar,2,3,4);
    else
      do_something_else(bar,4,3,2);
    Only the do..while() trick allows to put a ';' after the macro call without getting the if/else all messed up. This is the main difference between the do-while trick and a simple pair of curly braces around the macro body.

    Now you may say, why would I care about the ability to put a ';' in there? Well, maybe you don't --- but at least some C-aware editors will cause considerable mayhem to the auto-indentation if you have C statements without closing semicolons.

Reply
  • The issue is "making the macro look like a function call" which is a wonderful way to obfusciate the code.

    You've let yourself get confused. This is not about adding obfuscation, but about keeping it under control.

    The goal of the do..while(0) trick is not to make the macro call look like a function call --- the mere fact of it being a function-like macro with a parameter list already achieves that.

    The actual goal is to make the macro invocation not just look like a function call (including an argument list), but also actually act like one, in all possible contexts. The tricky one being

    if (foo)
      MYMACRO(bar,2,3,4);
    else
      do_something_else(bar,4,3,2);
    Only the do..while() trick allows to put a ';' after the macro call without getting the if/else all messed up. This is the main difference between the do-while trick and a simple pair of curly braces around the macro body.

    Now you may say, why would I care about the ability to put a ';' in there? Well, maybe you don't --- but at least some C-aware editors will cause considerable mayhem to the auto-indentation if you have C statements without closing semicolons.

Children
  • we know Drew has written a WndProc

    Well, I will admit to having written a WndProc or two in my checkered past. Mostly I do embedded communications stuff not related to Windows, though. That sort of switch statement is a common pattern for me. That may just mean I'm in a rut, of course, but there always seems to be this pesky little bit of code to pull parameters out of a message and pass them to a routine.

    There's usually a function lying around in some module that does what you want, but is (and properly so) independent of the "control" layer that invokes it. Such a routine probably takes a couple of parameters. When the system is controlled by messages, those messages generally convey the same information, maybe in more generic units or more abstract format.

        case
            {
            MsgA* msgA = (MsgA*)msg;
    
            SomeRoutine (msgA->a, msgA->b);
            break;
            }
    

    You could write SomeRoutine(MsgA* msg), but then SomeRoutine depends on the message format. SomeRoutine (int a, int b) is independent of the management layer, but then you have this little stub of code to parse out parameters and call SomeRoutine(). If the code were more involved, there could be a ParseSomeParms(MsgA*) function that calls SomeRoutine, but that creates an extra function for every case, and often it's such a tiny bit of code that it seems unnecessary to declare a function just to get the local variable. So I use the local block.

    Sometimes I use them just to limit the scope of a variable, or get stack reuse (from compilers other than C51), or to delay declaration of a variable until I can initialize it. C99 and C++ allow you to move the actual declaration, but you can get much the same effect in ANSI C by introducing a local block to give you a place to declare variables again.

    And sometimes I even use them as comments, just to visually delimit a range of code where something is true, say a critical section.

    Lots of these uses are hints that you might want an actual function instead, but when the code is small, the code generator seems to prefer the programmer not to force it to move things into the proper registers for function calls, and pass parameters when it could just reference variables from the enclosing scope.


    Only the do..while() trick allows to put a ';' after the macro call without getting the if/else all messed up.

    My stylistic preference is never to have a "bare" single-statement if or else clause, for the sake of consistency and problem avoidance. (I've seen too many people pull their hair out after sticking a debug printf into their "one-line" if statement or adding a bit extra during maintenance and believing the indentation.) So I don't run into this particular limitation.

        if ()
            {
            OneLinerCall();
            }
        else
    
    expands into
        if ()
            {
            {
            // OneLiner was really a macro
            };
            }
        else
    

    so there's no dangling else. Without the exterior braces, though, the macro-with-braces is a disaster waiting to happen, and you'll need the do-while in the macro for grammatical purposes at the point of call.

    (I actually prefer the if-else-endif syntax as it neatly avoids the issue of null statements and dangling elses entirely, but c'est le C.)