简体   繁体   中英

What does it mean the following C statement? ((int*) & var)

I have the following code in C to calculate a CRC16-USB for some data flows:

uint16_t DRV_CANFDSPI_CalculateCRC16(uint8_t* data, uint16_t size)
{
    uint16_t init = CRCBASE;
    uint8_t index;

    while (size-- != 0) {
        index = ((uint8_t*) & init)[1] ^ *data++;
        init = (init << 8) ^ crc16_table[index];
    }

    return init;
}

Where crc16_table is an array of some hex values of 2 bytes (like 0xAFF3) , and data is an array of hex values of 1 byte (like 0xA3) representing the data stream (aqcuired by other means). Size is the length of the data array.

I want to reproduce this piece of code in Python, but I don't know that this statement means:

index = ((uint8_t*) & init)[1] ^ *data++;

I would like to understand that does this statament means and does, so I can reproduce it in Python. I am not an expert in C but have some knowledge, and I mostly undestand the rest of the code, but this line is giving me a headache.

Thanks and have a nice day!

init has type uint16_t , so the expression &init has type "pointer to uint16_t ", or uint16_t * . The expression (uint8_t *) &init means "get the address of init , but treat that as the address of a uint8_t object, rather than a uint16_t object".

That address is then used with a subscript operator - ((uint8_t *) &init)[1] , which is basically equivalent to "treat init as an array of two uint8_t objects, and give me the value of the second element in that array".

Graphically:

      +---+
init: |   | <-- ((uint8_t *) &init)[0]
      +---+
      |   | <-- ((uint8_t *) &init)[1]
      +---+

So, basically, you're grabbing the lower 8 bits of init , bitwise XORing that with the value of the current byte of the input message, and then advancing data to point to the next byte of the input message.

I found a solution for my problem, with the following code:

def calculateCRC16(data):
    init = 0xFFFF
    for byte in data:
        index = (init >> 8) ^ byte
        init = ((init << 8) ^ crc16_table[index]) & 0xFFFF
    return init

I think it is fairly simple. I tested this code with the above one in C and the results are the same. The masking in Python in the variable init is necessary as Python does not limit int variables to a fixed bit size. Also, in C, lib should be included for the code to work.

The intent of the index = ((uint8_t*) & init)[1] ^ *data++; statement is to XOR the high eight bits of init with the next byte of data (and to increment `data). Unfortunately, it is written improperly.

In the statement index = ((uint8_t*) & init)[1] ^ *data++; :

  • & init takes the address of init (which was defined with uint16_t init = CRCBASE; ).
  • (uint8_t*) converts that address to a pointer to uint8_t . Further use of this pointer requires that uint8_t be a character type in the C implementation, which is likely but is not guaranteed by the C standard.
  • Applying [1] to this pointer fetches the next byte beyond where the pointer points. The fact that the second line uses init << 8 , which results in a value solely dependent on the *low** eight bits of init , suggests that the intent in this first line was to fetch the high eight bits of init .

However, the C standard does not require that the bytes of a uint16_t be in any particular order, so it is not assured that using [1] will fetch the desired bits. And it is unnecessary; using init >> 8 in place of ((uint8_t*) & init)[1] would provide the desired bits.

Thus, the code could have been simply:

while (size--)
    init = init << 8 ^ crc16_table[init>>8 ^ *data++];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM