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

发布于 2024-12-02 04:31:43 字数 850 浏览 0 评论 0原文

我想了解这个语法来修复它的 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:“++”需要左值

重新编码(希望它是正确的):

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



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

I want to understand this syntax to fix 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

假面具 2024-12-09 04:31:43
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) 给出了无法递增的右值。你的旧编译器有错误。

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.

涙—继续流 2024-12-09 04:31:43

该函数的 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]
 }
}

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]
 }
}
他夏了夏天 2024-12-09 04:31:43

打破该行:

  1. (unsigned char *)memptr - 这会将void*(参数)转换为unsigned char*
  2. + + - 后增量,即增量并返回先前的值(即指针增量 - 注意:这是本地副本)
  3. *() - this取消引用指针先前值的内容(所以现在我们有一个 unsigned char
  4. ^= xor 与当前值 crc

正如 ZeRemz 在他的评论中提到的,运算符的顺序此处应用的是产生此错误的原因。

要解决此问题,您需要了解初衷是什么(并修复)

  1. 更新指针并异或先前的值

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

  2. 更新字符的值并使用它之前的值(尽管这对于生成 CRC 没有多大意义)

    crc ^= (*reinterpret_cast(memptr))++;

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))++;

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文