理解语法:crc ^ = *((unsigned char *)memptr)++;

时间:2011-08-29 11:28:15

标签: c++ casting compiler-errors

我想了解这种语法来修复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

3 个答案:

答案 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)

打破这一行:

  1. (unsigned char *)memptr - 这会将void*(参数)转换为unsigned char*
  2. ++ - 后递增,即递增并返回先前的值(即指针递增 - 注意:这是本地副本)
  3. *() - 这取消了指针前一个值的内容(现在我们有一个unsigned char
  4. ^= xor,当前值为crc
  5. 正如ZeRemz在他的评论中提到的,这里应用的运算符的顺序就是产生这个错误的原因。

    要解决此问题,您需要了解最初的意图(并修复)

    1. 更新指针并xor前一个值

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

    2. 更新字符的值并使用它的先前值(尽管这对生成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]
 }
}