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:
(unsigned char *)memptr
- this casts thevoid*
(argument) to anunsigned char*
++
- post increment, i.e. increment and return the previous value (i.e. the pointer is incremented - note: this is a local copy)*()
- this dereferences the contents of the previous value of pointer (so now we have anunsigned char
)^=
xor with current value ofcrc
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)
Update the pointer and xor the previous value
unsigned char* t = reinterpret_cast<unsigned char*>(memptr); .. crc ^= *(t++);
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))++;
精彩评论