我想了解这种语法来修复crc16函数:
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 ;
}
它在较旧的编译器上运行代码,现在我已经
了错误:IntelliSense:表达式必须是可修改的左值
在这一行:
crc ^= *((unsigned char *)memptr)++;
编译错误:错误C2105:'++'需要l值
记录它(希望它是正确的):
unsigned char oldValue = *((unsigned char *)memptr);
++*((unsigned char *)memptr);
crc ^= oldValue; // <--- WRONG
crc ^= (*((unsigned char *)memptr))++; // <--- WRONG
答案 0 :(得分:4)
crc ^= *((unsigned char *)memptr)++;
将以上行更改为:
unsigned char *pchar=(unsigned char *)memptr; //casting to unsigned char*
crc = crc ^ pchar[0]; //XOR computation
memptr = ++pchar; //incrementing the pointer by 1 byte
您的代码不起作用,因为((unsigned char *)memptr)
给出了一个无法递增的右值。你的旧编译器有bug。
答案 1 :(得分:1)
打破这一行:
(unsigned char *)memptr
- 这会将void*
(参数)转换为unsigned char*
++
- 后递增,即递增并返回先前的值(即指针递增 - 注意:这是本地副本)*()
- 这取消了指针前一个值的内容(现在我们有一个unsigned char
)^=
xor,当前值为crc
正如ZeRemz在他的评论中提到的,这里应用的运算符的顺序就是产生这个错误的原因。
要解决此问题,您需要了解最初的意图(并修复)
更新指针并xor前一个值
unsigned char* t = reinterpret_cast<unsigned char*>(memptr);
..
crc ^= *(t++);
更新字符的值并使用它的先前值(尽管这对生成CRC没有多大意义)
crc ^= (*reinterpret_cast<unsigned char *>(memptr))++;
答案 2 :(得分:1)
此函数的ASM版本(不是优化的,但仍然是0x59字节,相对于我的编译器的C ++版本的0x69)。
如果您熟悉ASM,那么就足以理解所提到的C ++代码段和整个功能。
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]
}
}