Problem mit ~ Operator

Hallo,

beim Übernehmen von Code zur crc Berechnung von einem Arduino zum MapleMini bin ich auf ein Problem mit dem ~ Operator gestoßen, daß ich nicht verstehe.

Damit kann ich das Problem nachstellen.
Testen kann man es z.B. mit
https://www.tutorialspoint.com/compile_c_online.php

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

int main()
{
    bool isnotEqual;
    uint16_t ic;
    uint16_t crc = 0x2233;
    uint8_t byte_h = 0xdd;
    uint8_t byte_l = 0xcc;

    printf(" crc = %x\n", crc);
    ic = ~crc;
    printf("~crc = %x\n", ic);
    printf("byte_h shifted => %x\n\n", byte_h<<8);

    //--- Fall 1  not ok
    isnotEqual =  ( (~crc) != (byte_h << 8 | byte_l) );
    printf("isnotEqual = %u \n", isnotEqual);
   
    //--- Fall 2 ok
    isnotEqual = ( ic != (byte_h << 8 | byte_l));
    printf("isnotEqual = %u \n", isnotEqual);
    
    
    //--- Fall 3 ok
    isnotEqual = ( (uint16_t)(~crc) != (byte_h << 8 | byte_l));
    printf("isnotEqual = %u \n", isnotEqual);
    
    return 0;
}
$gcc -o main *.c -lm
$main
 crc = 2233
~crc = ddcc 
byte_h shifted => dd00 
isnotEqual = 1 
isnotEqual = 0 
isnotEqual = 0

Mit einem cast vor (~crc) funktionierts auch (Fall 3), nur warum brauch ich da ein cast (uint16_t), wenn crc schon uint16_t ist?

Gruß Ralf

byte_h ist "negativ", wenn es zu einem int hochgestuft wird

void setup() {
  bool isnotEqual;
  uint16_t ic;
  uint16_t crc = 0x2233;
  uint8_t byte_h = 0xdd;
  uint8_t byte_l = 0xcc;

  Serial.begin(115200); Serial.println();

  Serial.print("crc = 0x"); Serial.println(crc, HEX);
  ic = ~crc;
  Serial.print("~crc = 0x"); Serial.println(ic, HEX);
  Serial.print("byte_h bin => 0b"); Serial.println(byte_h, BIN);
  Serial.print("byte_h shifted => "); Serial.println(byte_h << 8, HEX);
  Serial.print("byte_h shifted and or-ed => "); Serial.println((byte_h << 8 | byte_l), HEX);
}

void loop() {}

crc = 0x2233
~crc = 0xDDCC
byte_h bin => 0b11011101
byte_h shifted => FFFFDD00
byte_h shifted and or-ed => FFFFDDCC

Die Rechnungen werden bei C++ standardmäßig immer als int ausgeführt. Beim mapleMini ist das ein 32Bit int. Der Typ der Variable wird immer erst bei der Zuweisung berücksichtigt. Deshalb ist für Berechnung/Vergleich erstmal egal welcher Typ crc ist. ~crc ist eine Berechnung, das Ergebnis also 32Bit lang. Da musst Du den Typ explizit angeben, wenn er berücksichtig werden soll.

Danke, damit wird es klarer.

J-M-LJackson

Da verhält sich der MapleMini, wie vermutet, anders:

crc = 0x2233
~crc = 0xDDCC
byte_h bin => 0b11011101
byte_h shifted => DD00
byte_h shifted and or-ed => DDCC

MicroBahner
Beim mapleMini ist das ein 32Bit int.

Wird dann bei "uint32_t crc" intern mit uint32_t gerechnet?

Wenn ich bei meinem Beispiel crc als uint32_t und byte als uint16_t definiere, dann passen alle 3 Fälle

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

int main()
{
    bool isnotEqual;
    uint32_t ic;
    uint32_t crc = 0x11223344;
    uint16_t byte_h = 0xeedd;
    uint16_t byte_l = 0xccbb;

    printf(" crc = %x\n", crc);
    ic = ~crc;
    printf("~crc = %x\n", ic);
    printf("byte_h shifted => %x\n\n", byte_h<<16);

    //--- Fall 1  ok
    isnotEqual =  ( (~crc) != (byte_h << 16 | byte_l) );
    printf("isnotEqual = %u \n", isnotEqual);
   
    //--- Fall 2 ok
    isnotEqual = ( ic != (byte_h << 16 | byte_l));
    printf("isnotEqual = %u \n", isnotEqual);
    
    
    //--- Fall 3 ok
    isnotEqual = ( (uint32_t)(~crc) != (byte_h << 16 | byte_l));
    printf("isnotEqual = %u \n", isnotEqual);
    
    return 0;
}

Ist es dann so korrekt?
isnotEqual = ( (uint16_t)(~crc) != (byte_h << 8 | byte_l));

Wenn du dich nicht auf dein verwirrendes Beispiel mit
uint32_t crc = 0x11223344;
uint16_t byte_h;
beziehst, sondern auf den Anfangs-Post #1, dann ja. Genau das cast passiert ja durch deine Hilfsvariable ic.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.