user40555: I am using an Arduino to read information from an EEPROM chip over I2C with the code I found here:
https://playground.arduino.cc/Code/I2CEEPROM
It works great for int and char values but I also need to read short, long, and float values. 
They are stored in this order:  1510543923
is stored as: 01011010 00001001 00010010 00110011
How can I read multiple bytes into a single variable of these types?
I tried the following but it gives me a 16 bit number:
i2c_eeprom_read_buffer(0x50, 25, (byte *)bytes, 4);
long j = (bytes[3] << 0) + (bytes[2] << 8) + (bytes[1] << 16) + (bytes[0] << 24);


user10214: It gives you a 16-bit integer because the compiler automatically makes casts. In particular:

byte << int returns int
int + int returns int

So your (bytes[1] << 16) is converted to an int, and consequently gets zeroed.
I tried to simulate this code; the results are shown as comments
int a = 0x1234;
long b = a << 8;
long c = a << 8L;
long d = ((long)a) << 8;
Serial.println(a); // a is 0x1234
Serial.println(b); // b is 0x3400
Serial.println(c); // c is 0x3400
Serial.println(d); // d is 0x123400

Personally I'd bet that int << long would result in a long, but apparently I'm wrong.
In any case, you should write
long j= (bytes[3] << 0) + (bytes[2] << 8) + (((unsigned long)bytes[1]) << 16) + (((unsigned long)bytes[0]) << 24);

This should fix your error. In any case, you can also simply write
long write_value;
i2c_eeprom_write_page(0x50, 25, (byte *)&write_value, sizeof(write_value));
long read_value;
i2c_eeprom_read_buffer(0x50, 25, (byte *)&read_value, sizeof(read_value));

Please note that accessing directly the pointers, like in this case, will respect the endianness of the compiler. In the case of a big endian implementation, the long with value 0x12345678 will be saved as 12 34 56 78, while with a little endian implementation it will be saved as 78 56 34 12. This is not a problem if you always use the same platform, but if you are trying to transfer information over a network you will have to ensure that all the devices have the same endianness or manually correct it

user7508: 
1510543923 is stored as: 01011010 00001001 00010010 00110011

This is known as “big endian”, or “MSB first”, because the most
significant byte (MSB, here 01011010) comes first.
I recommend against this order. If you can, swap all the bytes and store
the value LSB first, i.e. with the least significant byte first, and the
most significant byte last. This will make your life easier since it's
the order used internally in the Arduino. If you can go little endian,
then you will be able to read the data straight into the required
variable, with no conversion needed, as in:
i2c_eeprom_read_buffer(0x50, 25, (byte *) &j, sizeof j);

and it will work identically with any data type.
If you cannot choose the byte order (maybe you cannot control what is
inside the EEPROM), then you will have to reverse all the bytes. You can
do this either with bit shifts or by explicitly moving bytes.

bytes[1] << 16

This will not work. Per the rules of the C++ language, bytes[1] is
implicitly promoted to int type before the shift, then it is shifted
as an int. But on your Arduino an int is 16-bits long, thus by
shifting it 16 positions you are dropping off all of the bits.
Actually, this is even worse: you are invoking what is known as
undefined behavior, meaning that it is considered nonsense and the
compiler is free to interpret however it wants.
To do this properly, you first have to explicitly cast bytes[i] to
unsigned long. It has to be unsigned because changing the sign bit on
a long by bit shifting is also undefined behavior. Thus, the proper
way of reconstructing the number via bit shifts is:
long j = ((unsigned long) bytes[3] << 0)
       | ((unsigned long) bytes[2] << 8)
       | ((unsigned long) bytes[1] << 16)
       | ((unsigned long) bytes[0] << 24);

This is portable (it should also work on big-endian architectures) but
only works with integral types, not with floats.
For reconstructing a float, my preferred option would be to use a
union, in order to access the bytes of the variable explicitly. Then
you just have to copy the bytes from the buffer to the union in
reverse order:
union { float f; byte b[4]; } data;
data.b[0] = bytes[3];
data.b[1] = bytes[2];
data.b[2] = bytes[1];
data.b[3] = bytes[0];
float x = data.f;

One nice thing about this approach is that it works with any data type.

40555: <p>I am using an Arduino to read information from an EEPROM chip over I2C with the code I found here:
<a href="https://playground.arduino.cc/Code/I2CEEPROM" rel="nofollow noreferrer">https://playground.arduino.cc/Code/I2CEEPROM</a></p>

<p>It works great for <em>int</em> and <em>char</em> values but I also need to read <em>short</em>, <em>long</em>, and <em>float</em> values. </p>

<p>They are stored in this order:  1510543923<br>
is stored as: 01011010 00001001 00010010 00110011</p>

<p>How can I read multiple bytes into a single variable of these types?</p>

<p>I tried the following but it gives me a 16 bit number:</p>

<pre class="lang-cpp prettyprint-override"><code>i2c_eeprom_read_buffer(0x50, 25, (byte *)bytes, 4);
long j = (bytes[3] &lt;&lt; 0) + (bytes[2] &lt;&lt; 8) + (bytes[1] &lt;&lt; 16) + (bytes[0] &lt;&lt; 24);
</code></pre>
 10214: <p>It gives you a 16-bit integer because the compiler automatically makes casts. In particular:</p>

<ul>
<li><code>byte &lt;&lt; int</code> returns <code>int</code></li>
<li><code>int + int</code> returns <code>int</code></li>
</ul>

<p>So your <code>(bytes[1] &lt;&lt; 16)</code> is converted to an <code>int</code>, and consequently gets zeroed.</p>

<p>I tried to simulate this code; the results are shown as comments</p>

<pre><code>int a = 0x1234;
long b = a &lt;&lt; 8;
long c = a &lt;&lt; 8L;
long d = ((long)a) &lt;&lt; 8;
Serial.println(a); // a is 0x1234
Serial.println(b); // b is 0x3400
Serial.println(c); // c is 0x3400
Serial.println(d); // d is 0x123400
</code></pre>

<p>Personally I'd bet that <code>int &lt;&lt; long</code> would result in a <code>long</code>, but apparently I'm wrong.</p>

<p>In any case, you should write</p>

<pre><code>long j= (bytes[3] &lt;&lt; 0) + (bytes[2] &lt;&lt; 8) + (((unsigned long)bytes[1]) &lt;&lt; 16) + (((unsigned long)bytes[0]) &lt;&lt; 24);
</code></pre>

<p>This should fix your error. In any case, you can also simply write</p>

<pre><code>long write_value;
i2c_eeprom_write_page(0x50, 25, (byte *)&amp;write_value, sizeof(write_value));
long read_value;
i2c_eeprom_read_buffer(0x50, 25, (byte *)&amp;read_value, sizeof(read_value));
</code></pre>

<p>Please note that accessing directly the pointers, like in this case, will respect the endianness of the compiler. In the case of a big endian implementation, the long with value <code>0x12345678</code> will be saved as <code>12 34 56 78</code>, while with a little endian implementation it will be saved as <code>78 56 34 12</code>. This is not a problem if you always use the same platform, but if you are trying to transfer information over a network you will have to ensure that all the devices have the same endianness or manually correct it</p>
 7508: <blockquote>
  <p>1510543923 is stored as: 01011010 00001001 00010010 00110011</p>
</blockquote>

<p>This is known as “big endian”, or “MSB first”, because the most
significant byte (MSB, here 01011010) comes first.</p>

<p>I recommend against this order. If you can, swap all the bytes and store
the value LSB first, i.e. with the least significant byte first, and the
most significant byte last. This will make your life easier since it's
the order used internally in the Arduino. If you can go little endian,
then you will be able to read the data straight into the required
variable, with no conversion needed, as in:</p>

<pre><code>i2c_eeprom_read_buffer(0x50, 25, (byte *) &amp;j, sizeof j);
</code></pre>

<p>and it will work identically with any data type.</p>

<p>If you cannot choose the byte order (maybe you cannot control what is
inside the EEPROM), then you will have to reverse all the bytes. You can
do this either with bit shifts or by explicitly moving bytes.</p>

<blockquote>
  <p><code>bytes[1] &lt;&lt; 16</code></p>
</blockquote>

<p>This will not work. Per the rules of the C++ language, <code>bytes[1]</code> is
implicitly promoted to <code>int</code> type before the shift, then it is shifted
as an <code>int</code>. But on your Arduino an <code>int</code> is 16-bits long, thus by
shifting it 16 positions you are dropping off <em>all</em> of the bits.
Actually, this is even worse: you are invoking what is known as
<em>undefined behavior</em>, meaning that it is considered nonsense and the
compiler is free to interpret however it wants.</p>

<p>To do this properly, you first have to <em>explicitly</em> cast <code>bytes[i]</code> to
<code>unsigned long</code>. It has to be unsigned because changing the sign bit on
a <code>long</code> by bit shifting is also undefined behavior. Thus, the proper
way of reconstructing the number via bit shifts is:</p>

<pre><code>long j = ((unsigned long) bytes[3] &lt;&lt; 0)
       | ((unsigned long) bytes[2] &lt;&lt; 8)
       | ((unsigned long) bytes[1] &lt;&lt; 16)
       | ((unsigned long) bytes[0] &lt;&lt; 24);
</code></pre>

<p>This is portable (it should also work on big-endian architectures) but
only works with integral types, not with floats.</p>

<p>For reconstructing a float, my preferred option would be to use a
<code>union</code>, in order to access the bytes of the variable explicitly. Then
you just have to copy the bytes from the buffer to the <code>union</code> in
reverse order:</p>

<pre><code>union { float f; byte b[4]; } data;
data.b[0] = bytes[3];
data.b[1] = bytes[2];
data.b[2] = bytes[1];
data.b[3] = bytes[0];
float x = data.f;
</code></pre>

<p>One nice thing about this approach is that it works with any data type.</p>
