Receiving a 24-bit Number

I have a sensor hooked up to the I2C lines of Arduino. The sensor outputs a 24-bit number and is read with the following code.

  uint8_t pMMSB = Wire.read();
  uint8_t pMLSB = Wire.read();
  uint8_t pLMSB = Wire.read(); 

  long p_dout = pMMSB << 16 | pMLSB << 8 | pLMSB; //3 Byte (24 bits) Varible

Using this code I get a p_dout value of around -31000. I decided to print out the MMSB, MLSB, LMSB, and got the following.

pMMSB = 171 (10101011)
pMLSB = 136 (10001000)
pLMSB = 100 (01100100)

I put the 3 bytes together and got 11241572 (10101011-10001000-01100100), which is the correct value I should be getting from my sensor! I have tried long, double, unsigned long, float, but nothing gives me the correct value I should be seeing. How do I read a 24-bit value with Arduino?

I thought storing the variable as a 32-bit long would do the trick, but apparently not.

cast the shift 16

uint32_t p_dout = (uint32_t)pMMSB << 16 | pMLSB << 8 | pLMSB; //3 Byte (24 bits) Varible

cast the shift 16

No, that is not enough. The shift 8 needs to be specified as unsigned. The automatic integer promotion(signed) from the bit shift <<8 is creating the negative values.

void setup() {
  Serial.begin(115200);
  byte pMMSB = 171;//(10101011)
  byte pMLSB = 136;//(10001000)
  byte pLMSB = 100;//(01100100)

  int32_t p_dout = (int32_t)pMMSB << 16 | (uint16_t)pMLSB << 8 | pLMSB;
  //int32_t p_dout = (int32_t)pMMSB << 16 | pMLSB << 8 | pLMSB;
  
  Serial.println(p_dout);
  Serial.println(p_dout,BIN);
}

void loop() {}

the safest is to use unsigned integers and to cast all variables before shifting to the ultimate formatuint32_t p_dout = (uint32_t)pMMSB << 16 | (uint32_t)pMLSB << 8 | pLMSB;