Понимание синтаксиса: crc ^ = * ((unsigned char *) memptr) ++; - PullRequest
2 голосов
/ 29 августа 2011

Я хочу понять этот синтаксис, чтобы исправить его для функции 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: выражение должно быть изменяемым lvalue

в этой строке:

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

Ошибка компилятора: ошибка C2105: для "++" необходимо значение l

Записано на него (надеюсь, это правильно):

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



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

Ответы [ 3 ]

4 голосов
/ 29 августа 2011
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) дает значение, которое нельзя увеличить.У вашего старого компилятора была ошибка.

1 голос
/ 29 августа 2011

ASM-версия этой функции (не такая оптимизированная, но все же 0x59 байт по сравнению с 0x69 моего компилятора версии C ++).

Если вы знакомы с 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]
 }
}
1 голос
/ 29 августа 2011

Разбейте эту линию:

  1. (unsigned char *)memptr - это приводит void* (аргумент) к unsigned char*
  2. ++ - постинкремент, то есть инкремент и возврат предыдущего значения (т. Е. Увеличивается указатель - примечание: это локальная копия)
  3. *() - это разыменовывает содержимое предыдущего значения указателя (так что теперь у нас есть unsigned char)
  4. ^= xor с текущим значением crc

Как ZeRemz упоминает в своем комментарии, порядок операторов, применяемых здесь, является причиной этой ошибки.

Чтобы исправить это, вам нужно понять, каково первоначальное намерение (и исправляет)

  1. Обновить указатель и xor предыдущего значения

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

  2. Обновите значение символа и используйте его предыдущее значение (хотя это не имеет особого смысла для генерации CRC)

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

...