开发者

Understanding the syntax : crc ^= *((unsigned char *)memptr)++;

I want to understand this syntax to fi开发者_C百科x it for crc16 function :

unsigned short crc16(void *memptr, int len) {
  int j;
  unsigned short crc = CRC16_INIT ;
  while(len--){
    crc ^= *((unsigned char *)memptr)++;
    for(j=0; j<8; j++){
      if(crc & 1)
        crc =(USHORT)( (crc>>1) ^ CRC16_POLY );
      else
        crc =(USHORT)( crc>>1);
    }//for
  }//while
  return crc ;
}

it was working code on older compiler and now I 've got

error : IntelliSense: expression must be a modifiable lvalue

on this line:

crc ^= *((unsigned char *)memptr)++;

Compiler error : error C2105: '++' needs l-value

Recoded to it (hope it's correct):

unsigned char oldValue = *((unsigned char *)memptr);
++*((unsigned char *)memptr);
crc ^= oldValue; // <--- WRONG



crc ^= (*((unsigned char *)memptr))++;  // <--- WRONG


crc ^= *((unsigned char *)memptr)++;

Change the above line to this:

unsigned char *pchar=(unsigned char *)memptr; //casting to unsigned char*
crc = crc ^ pchar[0];                          //XOR computation
memptr = ++pchar;                           //incrementing the pointer by 1 byte

Your code doesn't work because ((unsigned char *)memptr) gives a rvalue which cannot be incremented. Your old compiler had bug.


ASM-version of this function (not that optimized, but still 0x59 bytes vs my compiler's 0x69 of C++ version).

If you are familiar with ASM, it will be enough to understand mentioned C++ code segment and the whole function overall.

unsigned short crc16(void *memptr, int len)
{
 unsigned short crc = 0;//CRC16_INIT;

 __asm
 {
  MOV       ESI, len
while_s:
  DEC       ESI
  CMP       ESI, 0
  JL        while_e
  XOR       EAX, EAX
  MOV       AX, WORD PTR DS:[crc]
  MOV       EBX, len
  SUB       EBX, ESI
  DEC       EBX
  MOV       ECX, memptr
  MOV       BL, BYTE PTR DS:[ECX+EBX]
  XOR       AL, BL
  XOR       BL, BL
 for_s:
  CMP       BL, 8
  JGE       for_e
  INC       BL
  MOV       DX, AX
  SHR       AX, 1
  AND       DX, 1
  JE        for_j
  XOR       AX, 0xA001//CRC16_POLY
 for_j:
  JMP       for_s
 for_e:
  MOV       WORD PTR DS:[crc], AX
  JMP       while_s
while_e:
  XOR       EAX, EAX
  MOV       AX, WORD PTR DS:[crc]
 }
}


Break that line up:

  1. (unsigned char *)memptr - this casts the void* (argument) to an unsigned char*
  2. ++ - post increment, i.e. increment and return the previous value (i.e. the pointer is incremented - note: this is a local copy)
  3. *() - this dereferences the contents of the previous value of pointer (so now we have an unsigned char)
  4. ^= xor with current value of crc

As ZeRemz mentions in his comment, the order of the operators applied here is what is generating this error.

To fix, this you need to understand what the original intention is (and fixes)

  1. Update the pointer and xor the previous value

    unsigned char* t = reinterpret_cast<unsigned char*>(memptr); .. crc ^= *(t++);

  2. Update the value of the character and use it's previous value (though this does not make much sense for generating a CRC)

    crc ^= (*reinterpret_cast<unsigned char *>(memptr))++;

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜